github.com/goldeneggg/goa@v1.3.1/goagen/gen_app/writers_test.go (about) 1 package genapp_test 2 3 import ( 4 "io/ioutil" 5 "os" 6 7 "github.com/goadesign/goa/design" 8 "github.com/goadesign/goa/design/apidsl" 9 "github.com/goadesign/goa/dslengine" 10 "github.com/goadesign/goa/goagen/codegen" 11 "github.com/goadesign/goa/goagen/gen_app" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("ContextsWriter", func() { 17 var writer *genapp.ContextsWriter 18 var filename string 19 var workspace *codegen.Workspace 20 21 JustBeforeEach(func() { 22 var err error 23 workspace, err = codegen.NewWorkspace("test") 24 Ω(err).ShouldNot(HaveOccurred()) 25 pkg, err := workspace.NewPackage("contexts") 26 Ω(err).ShouldNot(HaveOccurred()) 27 src, err := pkg.CreateSourceFile("test.go") 28 Ω(err).ShouldNot(HaveOccurred()) 29 defer src.Close() 30 filename = src.Abs() 31 writer, err = genapp.NewContextsWriter(filename) 32 Ω(err).ShouldNot(HaveOccurred()) 33 codegen.TempCount = 0 34 }) 35 36 AfterEach(func() { 37 workspace.Delete() 38 }) 39 40 Context("correctly configured", func() { 41 var f *os.File 42 BeforeEach(func() { 43 dslengine.Reset() 44 f, _ = ioutil.TempFile("", "") 45 filename = f.Name() 46 }) 47 48 AfterEach(func() { 49 os.Remove(filename) 50 }) 51 52 Context("with data", func() { 53 var params, headers *design.AttributeDefinition 54 var payload *design.UserTypeDefinition 55 var responses map[string]*design.ResponseDefinition 56 var routes []*design.RouteDefinition 57 58 var data *genapp.ContextTemplateData 59 60 BeforeEach(func() { 61 params = nil 62 headers = nil 63 payload = nil 64 responses = nil 65 routes = nil 66 data = nil 67 }) 68 69 JustBeforeEach(func() { 70 data = &genapp.ContextTemplateData{ 71 Name: "ListBottleContext", 72 ResourceName: "bottles", 73 ActionName: "list", 74 Params: params, 75 Payload: payload, 76 Headers: headers, 77 Responses: responses, 78 Routes: routes, 79 API: design.Design, 80 DefaultPkg: "", 81 } 82 }) 83 84 Context("with simple data", func() { 85 It("writes the simple contexts code", func() { 86 err := writer.Execute(data) 87 Ω(err).ShouldNot(HaveOccurred()) 88 b, err := ioutil.ReadFile(filename) 89 Ω(err).ShouldNot(HaveOccurred()) 90 written := string(b) 91 Ω(written).ShouldNot(BeEmpty()) 92 Ω(written).Should(ContainSubstring(emptyContext)) 93 Ω(written).Should(ContainSubstring(emptyContextFactory)) 94 }) 95 }) 96 97 Context("with a media type setting a ContentType", func() { 98 var contentType = "application/json" 99 100 BeforeEach(func() { 101 mediaType := &design.MediaTypeDefinition{ 102 UserTypeDefinition: &design.UserTypeDefinition{ 103 AttributeDefinition: &design.AttributeDefinition{ 104 Type: design.Object{"foo": {Type: design.String}}, 105 }, 106 }, 107 Identifier: "application/vnd.goa.test", 108 ContentType: contentType, 109 } 110 defView := &design.ViewDefinition{ 111 AttributeDefinition: mediaType.AttributeDefinition, 112 Name: "default", 113 Parent: mediaType, 114 } 115 mediaType.Views = map[string]*design.ViewDefinition{"default": defView} 116 design.Design = new(design.APIDefinition) 117 design.Design.MediaTypes = map[string]*design.MediaTypeDefinition{ 118 design.CanonicalIdentifier(mediaType.Identifier): mediaType, 119 } 120 design.ProjectedMediaTypes = make(map[string]*design.MediaTypeDefinition) 121 responses = map[string]*design.ResponseDefinition{"OK": { 122 Name: "OK", 123 Status: 200, 124 MediaType: mediaType.Identifier, 125 }} 126 }) 127 128 It("the generated code sets the Content-Type header", func() { 129 err := writer.Execute(data) 130 Ω(err).ShouldNot(HaveOccurred()) 131 b, err := ioutil.ReadFile(filename) 132 Ω(err).ShouldNot(HaveOccurred()) 133 written := string(b) 134 Ω(written).ShouldNot(BeEmpty()) 135 Ω(written).Should(ContainSubstring(`ctx.ResponseData.Header().Set("Content-Type", "` + contentType + `")`)) 136 }) 137 }) 138 139 Context("with a collection media type", func() { 140 BeforeEach(func() { 141 elemType := &design.MediaTypeDefinition{ 142 UserTypeDefinition: &design.UserTypeDefinition{ 143 AttributeDefinition: &design.AttributeDefinition{ 144 Type: design.Object{"foo": {Type: design.String}}, 145 }, 146 }, 147 Identifier: "application/vnd.goa.test", 148 } 149 defView := &design.ViewDefinition{ 150 AttributeDefinition: elemType.AttributeDefinition, 151 Name: "default", 152 Parent: elemType, 153 } 154 elemType.Views = map[string]*design.ViewDefinition{"default": defView} 155 design.Design = new(design.APIDefinition) 156 design.Design.MediaTypes = map[string]*design.MediaTypeDefinition{ 157 design.CanonicalIdentifier(elemType.Identifier): elemType, 158 } 159 design.ProjectedMediaTypes = make(map[string]*design.MediaTypeDefinition) 160 mediaType := apidsl.CollectionOf(elemType) 161 dslengine.Execute(mediaType.DSL(), mediaType) 162 responses = map[string]*design.ResponseDefinition{"OK": { 163 Name: "OK", 164 Status: 200, 165 Type: mediaType, 166 }} 167 }) 168 169 It("the generated code sets the response to an empty collection if value is nil", func() { 170 err := writer.Execute(data) 171 Ω(err).ShouldNot(HaveOccurred()) 172 b, err := ioutil.ReadFile(filename) 173 Ω(err).ShouldNot(HaveOccurred()) 174 written := string(b) 175 Ω(written).ShouldNot(BeEmpty()) 176 Ω(written).Should(ContainSubstring(` if r == nil { 177 r = Collection{} 178 } 179 return ctx.ResponseData.Service.Send(ctx.Context, 200, r)`)) 180 }) 181 }) 182 183 Context("with an integer param", func() { 184 var ( 185 intParam *design.AttributeDefinition 186 dataType design.Object 187 validation *dslengine.ValidationDefinition 188 ) 189 190 BeforeEach(func() { 191 intParam = &design.AttributeDefinition{Type: design.Integer} 192 dataType = design.Object{ 193 "param": intParam, 194 } 195 validation = &dslengine.ValidationDefinition{} 196 params = &design.AttributeDefinition{ 197 Type: dataType, 198 Validation: validation, 199 } 200 }) 201 202 It("writes the integer contexts code", func() { 203 err := writer.Execute(data) 204 Ω(err).ShouldNot(HaveOccurred()) 205 b, err := ioutil.ReadFile(filename) 206 Ω(err).ShouldNot(HaveOccurred()) 207 written := string(b) 208 Ω(written).ShouldNot(BeEmpty()) 209 Ω(written).Should(ContainSubstring(intContext)) 210 Ω(written).Should(ContainSubstring(intContextFactory)) 211 }) 212 213 Context("with a default value", func() { 214 BeforeEach(func() { 215 intParam.SetDefault(2) 216 }) 217 218 It("writes the integer contexts code", func() { 219 err := writer.Execute(data) 220 Ω(err).ShouldNot(HaveOccurred()) 221 b, err := ioutil.ReadFile(filename) 222 Ω(err).ShouldNot(HaveOccurred()) 223 written := string(b) 224 Ω(written).ShouldNot(BeEmpty()) 225 Ω(written).Should(ContainSubstring(intDefaultContext)) 226 Ω(written).Should(ContainSubstring(intDefaultContextFactory)) 227 }) 228 }) 229 230 Context("with required attribute", func() { 231 BeforeEach(func() { 232 validation.Required = []string{"param"} 233 }) 234 235 It("writes the integer contexts code", func() { 236 err := writer.Execute(data) 237 Ω(err).ShouldNot(HaveOccurred()) 238 b, err := ioutil.ReadFile(filename) 239 Ω(err).ShouldNot(HaveOccurred()) 240 written := string(b) 241 Ω(written).ShouldNot(BeEmpty()) 242 Ω(written).Should(ContainSubstring(intRequiredContext)) 243 Ω(written).Should(ContainSubstring(intRequiredContextFactory)) 244 }) 245 246 Context("with a default value", func() { 247 BeforeEach(func() { 248 intParam.SetDefault(2) 249 }) 250 251 It("writes the integer contexts code", func() { 252 err := writer.Execute(data) 253 Ω(err).ShouldNot(HaveOccurred()) 254 b, err := ioutil.ReadFile(filename) 255 Ω(err).ShouldNot(HaveOccurred()) 256 written := string(b) 257 Ω(written).ShouldNot(BeEmpty()) 258 Ω(written).Should(ContainSubstring(intRequiredDefaultContext)) 259 Ω(written).Should(ContainSubstring(intRequiredDefaultContextFactory)) 260 }) 261 }) 262 }) 263 }) 264 265 Context("with an string param", func() { 266 var ( 267 strParam *design.AttributeDefinition 268 dataType design.Object 269 validation *dslengine.ValidationDefinition 270 ) 271 272 BeforeEach(func() { 273 strParam = &design.AttributeDefinition{Type: design.String} 274 dataType = design.Object{ 275 "param": strParam, 276 } 277 validation = &dslengine.ValidationDefinition{} 278 params = &design.AttributeDefinition{ 279 Type: dataType, 280 Validation: validation, 281 } 282 }) 283 284 It("writes the string contexts code", func() { 285 err := writer.Execute(data) 286 Ω(err).ShouldNot(HaveOccurred()) 287 b, err := ioutil.ReadFile(filename) 288 Ω(err).ShouldNot(HaveOccurred()) 289 written := string(b) 290 Ω(written).ShouldNot(BeEmpty()) 291 Ω(written).Should(ContainSubstring(strContext)) 292 Ω(written).Should(ContainSubstring(strContextFactory)) 293 }) 294 295 Context("with a default value", func() { 296 BeforeEach(func() { 297 strParam.SetDefault("foo") 298 }) 299 300 It("writes the string contexts code", func() { 301 err := writer.Execute(data) 302 Ω(err).ShouldNot(HaveOccurred()) 303 b, err := ioutil.ReadFile(filename) 304 Ω(err).ShouldNot(HaveOccurred()) 305 written := string(b) 306 Ω(written).ShouldNot(BeEmpty()) 307 Ω(written).Should(ContainSubstring(strNonOptionalContext)) 308 Ω(written).Should(ContainSubstring(strDefaultContextFactory)) 309 }) 310 }) 311 312 Context("with required attribute", func() { 313 BeforeEach(func() { 314 validation.Required = []string{"param"} 315 }) 316 317 It("writes the String contexts code", func() { 318 err := writer.Execute(data) 319 Ω(err).ShouldNot(HaveOccurred()) 320 b, err := ioutil.ReadFile(filename) 321 Ω(err).ShouldNot(HaveOccurred()) 322 written := string(b) 323 Ω(written).ShouldNot(BeEmpty()) 324 Ω(written).Should(ContainSubstring(strNonOptionalContext)) 325 Ω(written).Should(ContainSubstring(strRequiredContextFactory)) 326 }) 327 328 Context("with a default value", func() { 329 BeforeEach(func() { 330 strParam.SetDefault("foo") 331 }) 332 333 It("writes the integer contexts code", func() { 334 err := writer.Execute(data) 335 Ω(err).ShouldNot(HaveOccurred()) 336 b, err := ioutil.ReadFile(filename) 337 Ω(err).ShouldNot(HaveOccurred()) 338 written := string(b) 339 Ω(written).ShouldNot(BeEmpty()) 340 Ω(written).Should(ContainSubstring(strNonOptionalContext)) 341 Ω(written).Should(ContainSubstring(strDefaultContextFactory)) 342 }) 343 }) 344 }) 345 }) 346 347 Context("with a number param", func() { 348 var ( 349 numParam *design.AttributeDefinition 350 dataType design.Object 351 validation *dslengine.ValidationDefinition 352 ) 353 354 BeforeEach(func() { 355 numParam = &design.AttributeDefinition{Type: design.Number} 356 dataType = design.Object{ 357 "param": numParam, 358 } 359 validation = &dslengine.ValidationDefinition{} 360 params = &design.AttributeDefinition{ 361 Type: dataType, 362 Validation: validation, 363 } 364 }) 365 366 It("writes the number contexts code", func() { 367 err := writer.Execute(data) 368 Ω(err).ShouldNot(HaveOccurred()) 369 b, err := ioutil.ReadFile(filename) 370 Ω(err).ShouldNot(HaveOccurred()) 371 written := string(b) 372 Ω(written).ShouldNot(BeEmpty()) 373 Ω(written).Should(ContainSubstring(numContext)) 374 Ω(written).Should(ContainSubstring(numContextFactory)) 375 }) 376 377 Context("with a default value", func() { 378 BeforeEach(func() { 379 numParam.SetDefault(2.3) 380 }) 381 382 It("writes the number contexts code", func() { 383 err := writer.Execute(data) 384 Ω(err).ShouldNot(HaveOccurred()) 385 b, err := ioutil.ReadFile(filename) 386 Ω(err).ShouldNot(HaveOccurred()) 387 written := string(b) 388 Ω(written).ShouldNot(BeEmpty()) 389 Ω(written).Should(ContainSubstring(numNonOptionalContext)) 390 Ω(written).Should(ContainSubstring(numDefaultContextFactory)) 391 }) 392 }) 393 394 Context("with required attribute", func() { 395 BeforeEach(func() { 396 validation.Required = []string{"param"} 397 }) 398 399 It("writes the number contexts code", func() { 400 err := writer.Execute(data) 401 Ω(err).ShouldNot(HaveOccurred()) 402 b, err := ioutil.ReadFile(filename) 403 Ω(err).ShouldNot(HaveOccurred()) 404 written := string(b) 405 Ω(written).ShouldNot(BeEmpty()) 406 Ω(written).Should(ContainSubstring(numNonOptionalContext)) 407 Ω(written).Should(ContainSubstring(numRequiredContextFactory)) 408 }) 409 410 Context("with a default value", func() { 411 BeforeEach(func() { 412 numParam.SetDefault(2.3) 413 }) 414 415 It("writes the number contexts code", func() { 416 err := writer.Execute(data) 417 Ω(err).ShouldNot(HaveOccurred()) 418 b, err := ioutil.ReadFile(filename) 419 Ω(err).ShouldNot(HaveOccurred()) 420 written := string(b) 421 Ω(written).ShouldNot(BeEmpty()) 422 Ω(written).Should(ContainSubstring(numNonOptionalContext)) 423 Ω(written).Should(ContainSubstring(numDefaultContextFactory)) 424 }) 425 }) 426 }) 427 }) 428 429 Context("with a boolean param", func() { 430 var ( 431 boolParam *design.AttributeDefinition 432 dataType design.Object 433 validation *dslengine.ValidationDefinition 434 ) 435 436 BeforeEach(func() { 437 boolParam = &design.AttributeDefinition{Type: design.Boolean} 438 dataType = design.Object{ 439 "param": boolParam, 440 } 441 validation = &dslengine.ValidationDefinition{} 442 params = &design.AttributeDefinition{ 443 Type: dataType, 444 Validation: validation, 445 } 446 }) 447 448 It("writes the boolean contexts code", func() { 449 err := writer.Execute(data) 450 Ω(err).ShouldNot(HaveOccurred()) 451 b, err := ioutil.ReadFile(filename) 452 Ω(err).ShouldNot(HaveOccurred()) 453 written := string(b) 454 Ω(written).ShouldNot(BeEmpty()) 455 Ω(written).Should(ContainSubstring(boolContext)) 456 Ω(written).Should(ContainSubstring(boolContextFactory)) 457 }) 458 459 Context("with a default value", func() { 460 BeforeEach(func() { 461 boolParam.SetDefault(true) 462 }) 463 464 It("writes the boolean contexts code", func() { 465 err := writer.Execute(data) 466 Ω(err).ShouldNot(HaveOccurred()) 467 b, err := ioutil.ReadFile(filename) 468 Ω(err).ShouldNot(HaveOccurred()) 469 written := string(b) 470 Ω(written).ShouldNot(BeEmpty()) 471 Ω(written).Should(ContainSubstring(boolNonOptionalContext)) 472 Ω(written).Should(ContainSubstring(boolDefaultContextFactory)) 473 }) 474 }) 475 476 Context("with required attribute", func() { 477 BeforeEach(func() { 478 validation.Required = []string{"param"} 479 }) 480 481 It("writes the boolean contexts code", func() { 482 err := writer.Execute(data) 483 Ω(err).ShouldNot(HaveOccurred()) 484 b, err := ioutil.ReadFile(filename) 485 Ω(err).ShouldNot(HaveOccurred()) 486 written := string(b) 487 Ω(written).ShouldNot(BeEmpty()) 488 Ω(written).Should(ContainSubstring(boolNonOptionalContext)) 489 Ω(written).Should(ContainSubstring(boolRequiredContextFactory)) 490 }) 491 492 Context("with a default value", func() { 493 BeforeEach(func() { 494 boolParam.SetDefault(true) 495 }) 496 497 It("writes the boolean contexts code", func() { 498 err := writer.Execute(data) 499 Ω(err).ShouldNot(HaveOccurred()) 500 b, err := ioutil.ReadFile(filename) 501 Ω(err).ShouldNot(HaveOccurred()) 502 written := string(b) 503 Ω(written).ShouldNot(BeEmpty()) 504 Ω(written).Should(ContainSubstring(boolNonOptionalContext)) 505 Ω(written).Should(ContainSubstring(boolDefaultContextFactory)) 506 }) 507 }) 508 }) 509 }) 510 511 Context("with a array param", func() { 512 var ( 513 arrayParam *design.AttributeDefinition 514 dataType design.Object 515 validation *dslengine.ValidationDefinition 516 ) 517 518 BeforeEach(func() { 519 arrayParam = &design.AttributeDefinition{Type: &design.Array{ElemType: &design.AttributeDefinition{Type: design.String}}} 520 dataType = design.Object{ 521 "param": arrayParam, 522 } 523 validation = &dslengine.ValidationDefinition{} 524 params = &design.AttributeDefinition{ 525 Type: dataType, 526 Validation: validation, 527 } 528 }) 529 530 It("writes the array contexts code", func() { 531 err := writer.Execute(data) 532 Ω(err).ShouldNot(HaveOccurred()) 533 b, err := ioutil.ReadFile(filename) 534 Ω(err).ShouldNot(HaveOccurred()) 535 written := string(b) 536 Ω(written).ShouldNot(BeEmpty()) 537 Ω(written).Should(ContainSubstring(arrayContext)) 538 Ω(written).Should(ContainSubstring(arrayContextFactory)) 539 }) 540 541 Context("using a path param", func() { 542 BeforeEach(func() { 543 route := &design.RouteDefinition{Path: "/:param"} 544 routes = append(routes, route) 545 }) 546 547 It("writes the array contexts code", func() { 548 err := writer.Execute(data) 549 Ω(err).ShouldNot(HaveOccurred()) 550 b, err := ioutil.ReadFile(filename) 551 Ω(err).ShouldNot(HaveOccurred()) 552 written := string(b) 553 Ω(written).ShouldNot(BeEmpty()) 554 Ω(written).Should(ContainSubstring(arrayParamContextFactory)) 555 }) 556 }) 557 558 Context("with a default value", func() { 559 BeforeEach(func() { 560 arrayParam.SetDefault([]interface{}{"foo", "bar", "baz"}) 561 }) 562 563 It("writes the array contexts code", func() { 564 err := writer.Execute(data) 565 Ω(err).ShouldNot(HaveOccurred()) 566 b, err := ioutil.ReadFile(filename) 567 Ω(err).ShouldNot(HaveOccurred()) 568 written := string(b) 569 Ω(written).ShouldNot(BeEmpty()) 570 Ω(written).Should(ContainSubstring(arrayContext)) 571 Ω(written).Should(ContainSubstring(arrayDefaultContextFactory)) 572 }) 573 }) 574 575 Context("with required attribute", func() { 576 BeforeEach(func() { 577 validation.Required = []string{"param"} 578 }) 579 580 It("writes the array contexts code", func() { 581 err := writer.Execute(data) 582 Ω(err).ShouldNot(HaveOccurred()) 583 b, err := ioutil.ReadFile(filename) 584 Ω(err).ShouldNot(HaveOccurred()) 585 written := string(b) 586 Ω(written).ShouldNot(BeEmpty()) 587 Ω(written).Should(ContainSubstring(arrayContext)) 588 Ω(written).Should(ContainSubstring(arrayRequiredContextFactory)) 589 }) 590 591 Context("with a default value", func() { 592 BeforeEach(func() { 593 arrayParam.SetDefault([]interface{}{"foo", "bar", "baz"}) 594 }) 595 596 It("writes the array contexts code", func() { 597 err := writer.Execute(data) 598 Ω(err).ShouldNot(HaveOccurred()) 599 b, err := ioutil.ReadFile(filename) 600 Ω(err).ShouldNot(HaveOccurred()) 601 written := string(b) 602 Ω(written).ShouldNot(BeEmpty()) 603 Ω(written).Should(ContainSubstring(arrayContext)) 604 Ω(written).Should(ContainSubstring(arrayDefaultContextFactory)) 605 }) 606 }) 607 }) 608 }) 609 610 Context("with an int array param", func() { 611 var ( 612 arrayParam *design.AttributeDefinition 613 dataType design.Object 614 validation *dslengine.ValidationDefinition 615 ) 616 617 BeforeEach(func() { 618 arrayParam = &design.AttributeDefinition{Type: &design.Array{ElemType: &design.AttributeDefinition{Type: design.Integer}}} 619 dataType = design.Object{ 620 "param": arrayParam, 621 } 622 validation = &dslengine.ValidationDefinition{} 623 params = &design.AttributeDefinition{ 624 Type: dataType, 625 Validation: validation, 626 } 627 }) 628 629 It("writes the array contexts code", func() { 630 err := writer.Execute(data) 631 Ω(err).ShouldNot(HaveOccurred()) 632 b, err := ioutil.ReadFile(filename) 633 Ω(err).ShouldNot(HaveOccurred()) 634 written := string(b) 635 Ω(written).ShouldNot(BeEmpty()) 636 Ω(written).Should(ContainSubstring(intArrayContext)) 637 Ω(written).Should(ContainSubstring(intArrayContextFactory)) 638 }) 639 640 Context("with a default value", func() { 641 BeforeEach(func() { 642 arrayParam.SetDefault([]interface{}{1, 1, 2, 3, 5, 8}) 643 }) 644 645 It("writes the array contexts code", func() { 646 err := writer.Execute(data) 647 Ω(err).ShouldNot(HaveOccurred()) 648 b, err := ioutil.ReadFile(filename) 649 Ω(err).ShouldNot(HaveOccurred()) 650 written := string(b) 651 Ω(written).ShouldNot(BeEmpty()) 652 Ω(written).Should(ContainSubstring(intArrayContext)) 653 Ω(written).Should(ContainSubstring(intArrayDefaultContextFactory)) 654 }) 655 }) 656 657 Context("with required attribute", func() { 658 BeforeEach(func() { 659 validation.Required = []string{"param"} 660 }) 661 662 It("writes the array contexts code", func() { 663 err := writer.Execute(data) 664 Ω(err).ShouldNot(HaveOccurred()) 665 b, err := ioutil.ReadFile(filename) 666 Ω(err).ShouldNot(HaveOccurred()) 667 written := string(b) 668 Ω(written).ShouldNot(BeEmpty()) 669 Ω(written).Should(ContainSubstring(intArrayContext)) 670 Ω(written).Should(ContainSubstring(intArrayRequiredContextFactory)) 671 }) 672 673 Context("with a default value", func() { 674 BeforeEach(func() { 675 arrayParam.SetDefault([]interface{}{1, 1, 2, 3, 5, 8}) 676 }) 677 678 It("writes the array contexts code", func() { 679 err := writer.Execute(data) 680 Ω(err).ShouldNot(HaveOccurred()) 681 b, err := ioutil.ReadFile(filename) 682 Ω(err).ShouldNot(HaveOccurred()) 683 written := string(b) 684 Ω(written).ShouldNot(BeEmpty()) 685 Ω(written).Should(ContainSubstring(intArrayContext)) 686 Ω(written).Should(ContainSubstring(intArrayDefaultContextFactory)) 687 }) 688 }) 689 }) 690 }) 691 692 Context("with an param using a reserved keyword as name", func() { 693 BeforeEach(func() { 694 intParam := &design.AttributeDefinition{Type: design.Integer} 695 dataType := design.Object{ 696 "int": intParam, 697 } 698 params = &design.AttributeDefinition{ 699 Type: dataType, 700 } 701 }) 702 703 It("writes the contexts code", func() { 704 err := writer.Execute(data) 705 Ω(err).ShouldNot(HaveOccurred()) 706 b, err := ioutil.ReadFile(filename) 707 Ω(err).ShouldNot(HaveOccurred()) 708 written := string(b) 709 Ω(written).ShouldNot(BeEmpty()) 710 Ω(written).Should(ContainSubstring(resContext)) 711 Ω(written).Should(ContainSubstring(resContextFactory)) 712 }) 713 }) 714 715 Context("with a required param", func() { 716 BeforeEach(func() { 717 intParam := &design.AttributeDefinition{Type: design.Integer} 718 dataType := design.Object{ 719 "int": intParam, 720 } 721 required := &dslengine.ValidationDefinition{ 722 Required: []string{"int"}, 723 } 724 params = &design.AttributeDefinition{ 725 Type: dataType, 726 Validation: required, 727 } 728 }) 729 730 It("writes the contexts code", func() { 731 err := writer.Execute(data) 732 Ω(err).ShouldNot(HaveOccurred()) 733 b, err := ioutil.ReadFile(filename) 734 Ω(err).ShouldNot(HaveOccurred()) 735 written := string(b) 736 Ω(written).ShouldNot(BeEmpty()) 737 Ω(written).Should(ContainSubstring(requiredContext)) 738 Ω(written).Should(ContainSubstring(requiredContextFactory)) 739 }) 740 }) 741 742 Context("with a custom name param", func() { 743 BeforeEach(func() { 744 intParam := &design.AttributeDefinition{ 745 Type: design.Integer, 746 Metadata: dslengine.MetadataDefinition{ 747 "struct:field:name": []string{"custom"}, 748 }, 749 } 750 dataType := design.Object{ 751 "int": intParam, 752 } 753 params = &design.AttributeDefinition{ 754 Type: dataType, 755 } 756 }) 757 758 It("writes the contexts code", func() { 759 err := writer.Execute(data) 760 Ω(err).ShouldNot(HaveOccurred()) 761 b, err := ioutil.ReadFile(filename) 762 Ω(err).ShouldNot(HaveOccurred()) 763 written := string(b) 764 Ω(written).ShouldNot(BeEmpty()) 765 Ω(written).Should(ContainSubstring(customContext)) 766 Ω(written).Should(ContainSubstring(customContextFactory)) 767 }) 768 }) 769 770 Context("with a string header", func() { 771 BeforeEach(func() { 772 strHeader := &design.AttributeDefinition{Type: design.String} 773 dataType := design.Object{ 774 "Header": strHeader, 775 } 776 headers = &design.AttributeDefinition{ 777 Type: dataType, 778 } 779 }) 780 781 It("writes the contexts code", func() { 782 err := writer.Execute(data) 783 Ω(err).ShouldNot(HaveOccurred()) 784 b, err := ioutil.ReadFile(filename) 785 Ω(err).ShouldNot(HaveOccurred()) 786 written := string(b) 787 Ω(written).ShouldNot(BeEmpty()) 788 Ω(written).Should(ContainSubstring(strHeaderContext)) 789 Ω(written).Should(ContainSubstring(strHeaderContextFactory)) 790 }) 791 }) 792 793 Context("with a string header and param with the same name", func() { 794 BeforeEach(func() { 795 str := &design.AttributeDefinition{Type: design.String} 796 dataType := design.Object{ 797 "param": str, 798 } 799 params = &design.AttributeDefinition{ 800 Type: dataType, 801 } 802 headers = &design.AttributeDefinition{ 803 Type: dataType, 804 } 805 }) 806 807 It("writes the contexts code", func() { 808 err := writer.Execute(data) 809 Ω(err).ShouldNot(HaveOccurred()) 810 b, err := ioutil.ReadFile(filename) 811 Ω(err).ShouldNot(HaveOccurred()) 812 written := string(b) 813 Ω(written).ShouldNot(BeEmpty()) 814 Ω(written).Should(ContainSubstring(strContext)) 815 Ω(written).Should(ContainSubstring(strHeaderParamContextFactory)) 816 }) 817 }) 818 819 Context("with a simple payload", func() { 820 BeforeEach(func() { 821 design.Design = new(design.APIDefinition) 822 payload = &design.UserTypeDefinition{ 823 AttributeDefinition: &design.AttributeDefinition{Type: design.String}, 824 TypeName: "ListBottlePayload", 825 } 826 }) 827 828 It("writes the contexts code", func() { 829 err := writer.Execute(data) 830 Ω(err).ShouldNot(HaveOccurred()) 831 b, err := ioutil.ReadFile(filename) 832 Ω(err).ShouldNot(HaveOccurred()) 833 written := string(b) 834 Ω(written).ShouldNot(BeEmpty()) 835 Ω(written).Should(ContainSubstring(payloadContext)) 836 Ω(written).Should(ContainSubstring(payloadContextFactory)) 837 }) 838 }) 839 840 Context("with a object payload", func() { 841 BeforeEach(func() { 842 design.Design = new(design.APIDefinition) 843 intParam := &design.AttributeDefinition{Type: design.Integer} 844 strParam := &design.AttributeDefinition{Type: design.String} 845 dataType := design.Object{ 846 "int": intParam, 847 "str": strParam, 848 } 849 required := &dslengine.ValidationDefinition{ 850 Required: []string{"int"}, 851 } 852 payload = &design.UserTypeDefinition{ 853 AttributeDefinition: &design.AttributeDefinition{ 854 Type: dataType, 855 Validation: required, 856 }, 857 TypeName: "ListBottlePayload", 858 } 859 }) 860 861 It("writes the contexts code", func() { 862 err := writer.Execute(data) 863 Ω(err).ShouldNot(HaveOccurred()) 864 b, err := ioutil.ReadFile(filename) 865 Ω(err).ShouldNot(HaveOccurred()) 866 written := string(b) 867 Ω(written).ShouldNot(BeEmpty()) 868 Ω(written).Should(ContainSubstring(payloadObjContext)) 869 }) 870 871 var _ = Describe("IterateResponses", func() { 872 var resps []*design.ResponseDefinition 873 var testIt = func(r *design.ResponseDefinition) error { 874 resps = append(resps, r) 875 return nil 876 } 877 Context("with responses", func() { 878 BeforeEach(func() { 879 responses = map[string]*design.ResponseDefinition{ 880 "OK": {Status: 200}, 881 "Created": {Status: 201}, 882 } 883 }) 884 It("iterates responses in order", func() { 885 data.IterateResponses(testIt) 886 Ω(resps).Should(Equal([]*design.ResponseDefinition{ 887 responses["OK"], 888 responses["Created"], 889 })) 890 }) 891 }) 892 }) 893 }) 894 }) 895 }) 896 }) 897 898 var _ = Describe("ControllersWriter", func() { 899 var writer *genapp.ControllersWriter 900 var workspace *codegen.Workspace 901 var filename string 902 903 BeforeEach(func() { 904 var err error 905 workspace, err = codegen.NewWorkspace("test") 906 Ω(err).ShouldNot(HaveOccurred()) 907 pkg, err := workspace.NewPackage("controllers") 908 Ω(err).ShouldNot(HaveOccurred()) 909 src, err := pkg.CreateSourceFile("test.go") 910 Ω(err).ShouldNot(HaveOccurred()) 911 defer src.Close() 912 filename = src.Abs() 913 }) 914 915 JustBeforeEach(func() { 916 var err error 917 writer, err = genapp.NewControllersWriter(filename) 918 Ω(err).ShouldNot(HaveOccurred()) 919 }) 920 921 AfterEach(func() { 922 workspace.Delete() 923 }) 924 925 Context("correctly configured", func() { 926 BeforeEach(func() { 927 os.Create(filename) 928 }) 929 930 Context("with file servers", func() { 931 requestPath := "/swagger.json" 932 filePath := "swagger/swagger.json" 933 var origins []*design.CORSDefinition 934 var preflightPaths []string 935 936 var data []*genapp.ControllerTemplateData 937 938 BeforeEach(func() { 939 origins = nil 940 preflightPaths = nil 941 }) 942 943 JustBeforeEach(func() { 944 codegen.TempCount = 0 945 fileServer := &design.FileServerDefinition{ 946 FilePath: filePath, 947 RequestPath: requestPath, 948 } 949 d := &genapp.ControllerTemplateData{ 950 API: &design.APIDefinition{}, 951 Origins: origins, 952 PreflightPaths: preflightPaths, 953 Resource: "Public", 954 FileServers: []*design.FileServerDefinition{fileServer}, 955 } 956 data = []*genapp.ControllerTemplateData{d} 957 }) 958 959 It("writes the file server code", func() { 960 err := writer.Execute(data) 961 Ω(err).ShouldNot(HaveOccurred()) 962 b, err := ioutil.ReadFile(filename) 963 Ω(err).ShouldNot(HaveOccurred()) 964 written := string(b) 965 Ω(written).ShouldNot(BeEmpty()) 966 Ω(written).Should(ContainSubstring(simpleFileServer)) 967 }) 968 969 Context("with CORS", func() { 970 BeforeEach(func() { 971 origins = []*design.CORSDefinition{ 972 { 973 // NB: including backslash to ensure proper escaping 974 Origin: "here.example.com", 975 Headers: []string{"X-One", "X-Two"}, 976 Methods: []string{"GET", "POST"}, 977 Exposed: []string{"X-Three"}, 978 Credentials: true, 979 }, 980 } 981 preflightPaths = []string{"/public/star\\*star/*filepath"} 982 }) 983 984 It("writes the OPTIONS handler code", func() { 985 err := writer.Execute(data) 986 Ω(err).ShouldNot(HaveOccurred()) 987 b, err := ioutil.ReadFile(filename) 988 Ω(err).ShouldNot(HaveOccurred()) 989 written := string(b) 990 Ω(written).ShouldNot(BeEmpty()) 991 Ω(written).Should(ContainSubstring(fileServerOptionsHandler)) 992 }) 993 }) 994 }) 995 996 Context("with data", func() { 997 var actions, verbs, paths, contexts, unmarshals []string 998 var payloads []*design.UserTypeDefinition 999 var encoders, decoders []*genapp.EncoderTemplateData 1000 var origins []*design.CORSDefinition 1001 1002 var data []*genapp.ControllerTemplateData 1003 1004 BeforeEach(func() { 1005 actions = nil 1006 verbs = nil 1007 paths = nil 1008 contexts = nil 1009 unmarshals = nil 1010 payloads = nil 1011 encoders = nil 1012 decoders = nil 1013 origins = nil 1014 }) 1015 1016 JustBeforeEach(func() { 1017 codegen.TempCount = 0 1018 api := &design.APIDefinition{} 1019 d := &genapp.ControllerTemplateData{ 1020 Resource: "Bottles", 1021 Origins: origins, 1022 } 1023 as := make([]map[string]interface{}, len(actions)) 1024 for i, a := range actions { 1025 var unmarshal string 1026 var payload *design.UserTypeDefinition 1027 if i < len(unmarshals) { 1028 unmarshal = unmarshals[i] 1029 } 1030 if i < len(payloads) { 1031 payload = payloads[i] 1032 } 1033 as[i] = map[string]interface{}{ 1034 "Name": codegen.Goify(a, true), 1035 "DesignName": a, 1036 "Routes": []*design.RouteDefinition{ 1037 { 1038 Verb: verbs[i], 1039 Path: paths[i], 1040 }}, 1041 "Context": contexts[i], 1042 "Unmarshal": unmarshal, 1043 "Payload": payload, 1044 } 1045 } 1046 if len(as) > 0 { 1047 d.API = api 1048 d.Actions = as 1049 d.Encoders = encoders 1050 d.Decoders = decoders 1051 data = []*genapp.ControllerTemplateData{d} 1052 } else { 1053 data = nil 1054 } 1055 }) 1056 1057 Context("with missing data", func() { 1058 It("returns an empty string", func() { 1059 err := writer.Execute(data) 1060 Ω(err).ShouldNot(HaveOccurred()) 1061 b, err := ioutil.ReadFile(filename) 1062 Ω(err).ShouldNot(HaveOccurred()) 1063 written := string(b) 1064 Ω(written).Should(BeEmpty()) 1065 }) 1066 }) 1067 1068 Context("with a simple controller", func() { 1069 BeforeEach(func() { 1070 actions = []string{"list"} 1071 verbs = []string{"GET"} 1072 paths = []string{"/accounts/:accountID/bottles"} 1073 contexts = []string{"ListBottleContext"} 1074 }) 1075 1076 It("writes the controller code", func() { 1077 err := writer.Execute(data) 1078 Ω(err).ShouldNot(HaveOccurred()) 1079 b, err := ioutil.ReadFile(filename) 1080 Ω(err).ShouldNot(HaveOccurred()) 1081 written := string(b) 1082 Ω(written).ShouldNot(BeEmpty()) 1083 Ω(written).Should(ContainSubstring(simpleController)) 1084 Ω(written).Should(ContainSubstring(simpleMount)) 1085 }) 1086 }) 1087 1088 Context("with actions that take a payload", func() { 1089 BeforeEach(func() { 1090 actions = []string{"list"} 1091 verbs = []string{"GET"} 1092 paths = []string{"/accounts/:accountID/bottles"} 1093 contexts = []string{"ListBottleContext"} 1094 unmarshals = []string{"unmarshalListBottlePayload"} 1095 payloads = []*design.UserTypeDefinition{ 1096 { 1097 TypeName: "ListBottlePayload", 1098 AttributeDefinition: &design.AttributeDefinition{ 1099 Type: design.Object{ 1100 "id": &design.AttributeDefinition{ 1101 Type: design.String, 1102 }, 1103 }, 1104 }, 1105 }, 1106 } 1107 }) 1108 1109 It("writes the payload unmarshal function", func() { 1110 err := writer.Execute(data) 1111 Ω(err).ShouldNot(HaveOccurred()) 1112 b, err := ioutil.ReadFile(filename) 1113 Ω(err).ShouldNot(HaveOccurred()) 1114 written := string(b) 1115 Ω(written).Should(ContainSubstring(payloadNoValidationsObjUnmarshal)) 1116 }) 1117 }) 1118 Context("with actions that take a payload with a required validation", func() { 1119 BeforeEach(func() { 1120 actions = []string{"list"} 1121 required := &dslengine.ValidationDefinition{ 1122 Required: []string{"id"}, 1123 } 1124 verbs = []string{"GET"} 1125 paths = []string{"/accounts/:accountID/bottles"} 1126 contexts = []string{"ListBottleContext"} 1127 unmarshals = []string{"unmarshalListBottlePayload"} 1128 payloads = []*design.UserTypeDefinition{ 1129 { 1130 TypeName: "ListBottlePayload", 1131 AttributeDefinition: &design.AttributeDefinition{ 1132 Type: design.Object{ 1133 "id": &design.AttributeDefinition{ 1134 Type: design.String, 1135 }, 1136 }, 1137 Validation: required, 1138 }, 1139 }, 1140 } 1141 }) 1142 1143 It("writes the payload unmarshal function", func() { 1144 err := writer.Execute(data) 1145 Ω(err).ShouldNot(HaveOccurred()) 1146 b, err := ioutil.ReadFile(filename) 1147 Ω(err).ShouldNot(HaveOccurred()) 1148 written := string(b) 1149 Ω(written).Should(ContainSubstring(payloadObjUnmarshal)) 1150 }) 1151 }) 1152 1153 Context("with multiple controllers", func() { 1154 BeforeEach(func() { 1155 actions = []string{"list", "show"} 1156 verbs = []string{"GET", "GET"} 1157 paths = []string{"/accounts/:accountID/bottles", "/accounts/:accountID/bottles/:id"} 1158 contexts = []string{"ListBottleContext", "ShowBottleContext"} 1159 }) 1160 1161 It("writes the controllers code", func() { 1162 err := writer.Execute(data) 1163 Ω(err).ShouldNot(HaveOccurred()) 1164 b, err := ioutil.ReadFile(filename) 1165 Ω(err).ShouldNot(HaveOccurred()) 1166 written := string(b) 1167 Ω(written).ShouldNot(BeEmpty()) 1168 Ω(written).Should(ContainSubstring(multiController)) 1169 Ω(written).Should(ContainSubstring(multiMount)) 1170 }) 1171 }) 1172 1173 Context("with encoder and decoder maps", func() { 1174 BeforeEach(func() { 1175 actions = []string{"list"} 1176 verbs = []string{"GET"} 1177 paths = []string{"/accounts/:accountID/bottles"} 1178 contexts = []string{"ListBottleContext"} 1179 encoders = []*genapp.EncoderTemplateData{ 1180 { 1181 PackageName: "goa", 1182 Function: "NewEncoder", 1183 MIMETypes: []string{"application/json"}, 1184 }, 1185 } 1186 decoders = []*genapp.EncoderTemplateData{ 1187 { 1188 PackageName: "goa", 1189 Function: "NewDecoder", 1190 MIMETypes: []string{"application/json"}, 1191 }, 1192 } 1193 }) 1194 1195 It("writes the controllers code", func() { 1196 err := writer.Execute(data) 1197 Ω(err).ShouldNot(HaveOccurred()) 1198 b, err := ioutil.ReadFile(filename) 1199 Ω(err).ShouldNot(HaveOccurred()) 1200 written := string(b) 1201 Ω(written).ShouldNot(BeEmpty()) 1202 Ω(written).Should(ContainSubstring(encoderController)) 1203 }) 1204 }) 1205 1206 Context("with multiple origins", func() { 1207 BeforeEach(func() { 1208 actions = []string{"list"} 1209 verbs = []string{"GET"} 1210 paths = []string{"/accounts"} 1211 contexts = []string{"ListBottleContext"} 1212 origins = []*design.CORSDefinition{ 1213 { 1214 Origin: "here.example.com", 1215 Headers: []string{"X-One", "X-Two"}, 1216 Methods: []string{"GET", "POST"}, 1217 Exposed: []string{"X-Three"}, 1218 Credentials: true, 1219 }, 1220 { 1221 Origin: "there.example.com", 1222 Headers: []string{"*"}, 1223 Methods: []string{"*"}, 1224 }, 1225 } 1226 1227 }) 1228 1229 It("writes the controller code", func() { 1230 err := writer.Execute(data) 1231 Ω(err).ShouldNot(HaveOccurred()) 1232 b, err := ioutil.ReadFile(filename) 1233 Ω(err).ShouldNot(HaveOccurred()) 1234 written := string(b) 1235 Ω(written).ShouldNot(BeEmpty()) 1236 Ω(written).Should(ContainSubstring(originsIntegration)) 1237 Ω(written).Should(ContainSubstring(originsHandler)) 1238 }) 1239 }) 1240 1241 Context("with regexp origins", func() { 1242 BeforeEach(func() { 1243 actions = []string{"list"} 1244 verbs = []string{"GET"} 1245 paths = []string{"/accounts"} 1246 contexts = []string{"ListBottleContext"} 1247 origins = []*design.CORSDefinition{ 1248 { 1249 Origin: "[here|there].example.com", 1250 Headers: []string{"X-One", "X-Two"}, 1251 Methods: []string{"GET", "POST"}, 1252 Exposed: []string{"X-Three"}, 1253 Credentials: true, 1254 Regexp: true, 1255 }, 1256 { 1257 Origin: "there.example.com", 1258 Headers: []string{"*"}, 1259 Methods: []string{"*"}, 1260 }, 1261 } 1262 1263 }) 1264 1265 It("writes the controller code", func() { 1266 err := writer.Execute(data) 1267 Ω(err).ShouldNot(HaveOccurred()) 1268 b, err := ioutil.ReadFile(filename) 1269 Ω(err).ShouldNot(HaveOccurred()) 1270 written := string(b) 1271 Ω(written).ShouldNot(BeEmpty()) 1272 Ω(written).Should(ContainSubstring(originsIntegration)) 1273 Ω(written).Should(ContainSubstring(regexpOriginsHandler)) 1274 }) 1275 }) 1276 1277 }) 1278 }) 1279 }) 1280 1281 var _ = Describe("HrefWriter", func() { 1282 var writer *genapp.ResourcesWriter 1283 var workspace *codegen.Workspace 1284 var filename string 1285 1286 BeforeEach(func() { 1287 var err error 1288 workspace, err = codegen.NewWorkspace("test") 1289 Ω(err).ShouldNot(HaveOccurred()) 1290 pkg, err := workspace.NewPackage("controllers") 1291 Ω(err).ShouldNot(HaveOccurred()) 1292 src, err := pkg.CreateSourceFile("test.go") 1293 Ω(err).ShouldNot(HaveOccurred()) 1294 defer src.Close() 1295 filename = src.Abs() 1296 }) 1297 1298 JustBeforeEach(func() { 1299 var err error 1300 writer, err = genapp.NewResourcesWriter(filename) 1301 Ω(err).ShouldNot(HaveOccurred()) 1302 }) 1303 1304 AfterEach(func() { 1305 workspace.Delete() 1306 }) 1307 1308 Context("correctly configured", func() { 1309 Context("with data", func() { 1310 var canoTemplate string 1311 var canoParams []string 1312 var mediaType *design.MediaTypeDefinition 1313 1314 var data *genapp.ResourceData 1315 1316 BeforeEach(func() { 1317 mediaType = nil 1318 canoTemplate = "" 1319 canoParams = nil 1320 data = nil 1321 }) 1322 1323 JustBeforeEach(func() { 1324 data = &genapp.ResourceData{ 1325 Name: "Bottle", 1326 Identifier: "vnd.acme.com/resources", 1327 Description: "A bottle resource", 1328 Type: mediaType, 1329 CanonicalTemplate: canoTemplate, 1330 CanonicalParams: canoParams, 1331 } 1332 }) 1333 1334 Context("with missing resource type definition", func() { 1335 It("does not return an error", func() { 1336 err := writer.Execute(data) 1337 Ω(err).ShouldNot(HaveOccurred()) 1338 }) 1339 }) 1340 1341 Context("with a string resource", func() { 1342 BeforeEach(func() { 1343 attDef := &design.AttributeDefinition{ 1344 Type: design.String, 1345 } 1346 mediaType = &design.MediaTypeDefinition{ 1347 UserTypeDefinition: &design.UserTypeDefinition{ 1348 AttributeDefinition: attDef, 1349 TypeName: "Bottle", 1350 }, 1351 } 1352 }) 1353 It("does not return an error", func() { 1354 err := writer.Execute(data) 1355 Ω(err).ShouldNot(HaveOccurred()) 1356 }) 1357 }) 1358 1359 Context("with a user type resource", func() { 1360 BeforeEach(func() { 1361 intParam := &design.AttributeDefinition{Type: design.Integer} 1362 strParam := &design.AttributeDefinition{Type: design.String} 1363 dataType := design.Object{ 1364 "int": intParam, 1365 "str": strParam, 1366 } 1367 attDef := &design.AttributeDefinition{ 1368 Type: dataType, 1369 } 1370 mediaType = &design.MediaTypeDefinition{ 1371 UserTypeDefinition: &design.UserTypeDefinition{ 1372 AttributeDefinition: attDef, 1373 TypeName: "Bottle", 1374 }, 1375 } 1376 }) 1377 1378 Context("and a canonical action", func() { 1379 BeforeEach(func() { 1380 canoTemplate = "/bottles/%v" 1381 canoParams = []string{"id"} 1382 }) 1383 1384 It("writes the href method", func() { 1385 err := writer.Execute(data) 1386 Ω(err).ShouldNot(HaveOccurred()) 1387 b, err := ioutil.ReadFile(filename) 1388 Ω(err).ShouldNot(HaveOccurred()) 1389 written := string(b) 1390 Ω(written).ShouldNot(BeEmpty()) 1391 Ω(written).Should(ContainSubstring(simpleResourceHref)) 1392 }) 1393 }) 1394 1395 Context("and a canonical action with no param", func() { 1396 BeforeEach(func() { 1397 canoTemplate = "/bottles" 1398 }) 1399 1400 It("writes the href method", func() { 1401 err := writer.Execute(data) 1402 Ω(err).ShouldNot(HaveOccurred()) 1403 b, err := ioutil.ReadFile(filename) 1404 Ω(err).ShouldNot(HaveOccurred()) 1405 written := string(b) 1406 Ω(written).ShouldNot(BeEmpty()) 1407 Ω(written).Should(ContainSubstring(noParamHref)) 1408 }) 1409 }) 1410 }) 1411 }) 1412 }) 1413 }) 1414 1415 var _ = Describe("UserTypesWriter", func() { 1416 var writer *genapp.UserTypesWriter 1417 var workspace *codegen.Workspace 1418 var filename string 1419 1420 BeforeEach(func() { 1421 var err error 1422 workspace, err = codegen.NewWorkspace("test") 1423 Ω(err).ShouldNot(HaveOccurred()) 1424 pkg, err := workspace.NewPackage("controllers") 1425 Ω(err).ShouldNot(HaveOccurred()) 1426 src, err := pkg.CreateSourceFile("test.go") 1427 Ω(err).ShouldNot(HaveOccurred()) 1428 defer src.Close() 1429 filename = src.Abs() 1430 }) 1431 1432 JustBeforeEach(func() { 1433 var err error 1434 writer, err = genapp.NewUserTypesWriter(filename) 1435 Ω(err).ShouldNot(HaveOccurred()) 1436 }) 1437 1438 AfterEach(func() { 1439 workspace.Delete() 1440 }) 1441 1442 Context("correctly configured", func() { 1443 Context("with data", func() { 1444 var data *design.UserTypeDefinition 1445 var attDef *design.AttributeDefinition 1446 var typeName string 1447 1448 BeforeEach(func() { 1449 data = nil 1450 attDef = nil 1451 typeName = "" 1452 }) 1453 1454 JustBeforeEach(func() { 1455 data = &design.UserTypeDefinition{ 1456 AttributeDefinition: attDef, 1457 TypeName: typeName, 1458 } 1459 }) 1460 1461 Context("with a simple user type", func() { 1462 BeforeEach(func() { 1463 attDef = &design.AttributeDefinition{ 1464 Type: design.Object{ 1465 "name": &design.AttributeDefinition{ 1466 Type: design.String, 1467 }, 1468 }, 1469 } 1470 typeName = "SimplePayload" 1471 }) 1472 It("writes the simple user type code", func() { 1473 err := writer.Execute(data) 1474 Ω(err).ShouldNot(HaveOccurred()) 1475 b, err := ioutil.ReadFile(filename) 1476 Ω(err).ShouldNot(HaveOccurred()) 1477 written := string(b) 1478 Ω(written).ShouldNot(BeEmpty()) 1479 Ω(written).Should(ContainSubstring(simpleUserType)) 1480 }) 1481 }) 1482 1483 Context("with a user type including hash", func() { 1484 BeforeEach(func() { 1485 attDef = &design.AttributeDefinition{ 1486 Type: design.Object{ 1487 "name": &design.AttributeDefinition{ 1488 Type: design.String, 1489 }, 1490 "misc": &design.AttributeDefinition{ 1491 Type: &design.Hash{ 1492 KeyType: &design.AttributeDefinition{ 1493 Type: design.Integer, 1494 }, 1495 ElemType: &design.AttributeDefinition{ 1496 Type: &design.UserTypeDefinition{ 1497 AttributeDefinition: &design.AttributeDefinition{ 1498 Type: &design.UserTypeDefinition{ 1499 AttributeDefinition: &design.AttributeDefinition{ 1500 Type: design.Object{}, 1501 }, 1502 TypeName: "Misc", 1503 }, 1504 }, 1505 TypeName: "MiscPayload", 1506 }, 1507 }, 1508 }, 1509 }, 1510 }, 1511 } 1512 typeName = "ComplexPayload" 1513 }) 1514 It("writes the user type including hash", func() { 1515 err := writer.Execute(data) 1516 Ω(err).ShouldNot(HaveOccurred()) 1517 b, err := ioutil.ReadFile(filename) 1518 Ω(err).ShouldNot(HaveOccurred()) 1519 written := string(b) 1520 Ω(written).ShouldNot(BeEmpty()) 1521 Ω(written).Should(ContainSubstring(userTypeIncludingHash)) 1522 }) 1523 }) 1524 }) 1525 }) 1526 }) 1527 1528 const ( 1529 emptyContext = ` 1530 type ListBottleContext struct { 1531 context.Context 1532 *goa.ResponseData 1533 *goa.RequestData 1534 } 1535 ` 1536 1537 emptyContextFactory = ` 1538 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1539 var err error 1540 resp := goa.ContextResponse(ctx) 1541 resp.Service = service 1542 req := goa.ContextRequest(ctx) 1543 req.Request = r 1544 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1545 return &rctx, err 1546 } 1547 ` 1548 1549 intContext = ` 1550 type ListBottleContext struct { 1551 context.Context 1552 *goa.ResponseData 1553 *goa.RequestData 1554 Param *int 1555 } 1556 ` 1557 1558 intContextFactory = ` 1559 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1560 var err error 1561 resp := goa.ContextResponse(ctx) 1562 resp.Service = service 1563 req := goa.ContextRequest(ctx) 1564 req.Request = r 1565 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1566 paramParam := req.Params["param"] 1567 if len(paramParam) > 0 { 1568 rawParam := paramParam[0] 1569 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 1570 tmp2 := param 1571 tmp1 := &tmp2 1572 rctx.Param = tmp1 1573 } else { 1574 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 1575 } 1576 } 1577 return &rctx, err 1578 } 1579 ` 1580 1581 intDefaultContext = ` 1582 type ListBottleContext struct { 1583 context.Context 1584 *goa.ResponseData 1585 *goa.RequestData 1586 Param int 1587 } 1588 ` 1589 1590 intDefaultContextFactory = ` 1591 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1592 var err error 1593 resp := goa.ContextResponse(ctx) 1594 resp.Service = service 1595 req := goa.ContextRequest(ctx) 1596 req.Request = r 1597 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1598 paramParam := req.Params["param"] 1599 if len(paramParam) == 0 { 1600 rctx.Param = 2 1601 } else { 1602 rawParam := paramParam[0] 1603 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 1604 rctx.Param = param 1605 } else { 1606 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 1607 } 1608 } 1609 return &rctx, err 1610 } 1611 ` 1612 1613 intRequiredDefaultContext = ` 1614 type ListBottleContext struct { 1615 context.Context 1616 *goa.ResponseData 1617 *goa.RequestData 1618 Param int 1619 } 1620 ` 1621 1622 intRequiredDefaultContextFactory = ` 1623 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1624 var err error 1625 resp := goa.ContextResponse(ctx) 1626 resp.Service = service 1627 req := goa.ContextRequest(ctx) 1628 req.Request = r 1629 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1630 paramParam := req.Params["param"] 1631 if len(paramParam) == 0 { 1632 rctx.Param = 2 1633 } else { 1634 rawParam := paramParam[0] 1635 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 1636 rctx.Param = param 1637 } else { 1638 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 1639 } 1640 } 1641 return &rctx, err 1642 } 1643 ` 1644 1645 intRequiredContext = ` 1646 type ListBottleContext struct { 1647 context.Context 1648 *goa.ResponseData 1649 *goa.RequestData 1650 Param int 1651 } 1652 ` 1653 intRequiredContextFactory = ` 1654 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1655 var err error 1656 resp := goa.ContextResponse(ctx) 1657 resp.Service = service 1658 req := goa.ContextRequest(ctx) 1659 req.Request = r 1660 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1661 paramParam := req.Params["param"] 1662 if len(paramParam) == 0 { 1663 err = goa.MergeErrors(err, goa.MissingParamError("param")) 1664 } else { 1665 rawParam := paramParam[0] 1666 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 1667 rctx.Param = param 1668 } else { 1669 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 1670 } 1671 } 1672 return &rctx, err 1673 } 1674 ` 1675 1676 strContext = ` 1677 type ListBottleContext struct { 1678 context.Context 1679 *goa.ResponseData 1680 *goa.RequestData 1681 Param *string 1682 } 1683 ` 1684 1685 strContextFactory = ` 1686 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1687 var err error 1688 resp := goa.ContextResponse(ctx) 1689 resp.Service = service 1690 req := goa.ContextRequest(ctx) 1691 req.Request = r 1692 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1693 paramParam := req.Params["param"] 1694 if len(paramParam) > 0 { 1695 rawParam := paramParam[0] 1696 rctx.Param = &rawParam 1697 } 1698 return &rctx, err 1699 } 1700 ` 1701 1702 strNonOptionalContext = ` 1703 type ListBottleContext struct { 1704 context.Context 1705 *goa.ResponseData 1706 *goa.RequestData 1707 Param string 1708 } 1709 ` 1710 1711 strDefaultContextFactory = ` 1712 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1713 var err error 1714 resp := goa.ContextResponse(ctx) 1715 resp.Service = service 1716 req := goa.ContextRequest(ctx) 1717 req.Request = r 1718 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1719 paramParam := req.Params["param"] 1720 if len(paramParam) == 0 { 1721 rctx.Param = "foo" 1722 } else { 1723 rawParam := paramParam[0] 1724 rctx.Param = rawParam 1725 } 1726 return &rctx, err 1727 } 1728 ` 1729 1730 strRequiredContextFactory = ` 1731 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1732 var err error 1733 resp := goa.ContextResponse(ctx) 1734 resp.Service = service 1735 req := goa.ContextRequest(ctx) 1736 req.Request = r 1737 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1738 paramParam := req.Params["param"] 1739 if len(paramParam) == 0 { 1740 err = goa.MergeErrors(err, goa.MissingParamError("param")) 1741 } else { 1742 rawParam := paramParam[0] 1743 rctx.Param = rawParam 1744 } 1745 return &rctx, err 1746 } 1747 ` 1748 1749 strHeaderContext = ` 1750 type ListBottleContext struct { 1751 context.Context 1752 *goa.ResponseData 1753 *goa.RequestData 1754 Header *string 1755 } 1756 ` 1757 1758 strHeaderContextFactory = ` 1759 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1760 var err error 1761 resp := goa.ContextResponse(ctx) 1762 resp.Service = service 1763 req := goa.ContextRequest(ctx) 1764 req.Request = r 1765 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1766 headerHeader := req.Header["Header"] 1767 if len(headerHeader) > 0 { 1768 rawHeader := headerHeader[0] 1769 req.Params["Header"] = []string{rawHeader} 1770 rctx.Header = &rawHeader 1771 } 1772 return &rctx, err 1773 } 1774 ` 1775 1776 strHeaderParamContextFactory = ` 1777 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1778 var err error 1779 resp := goa.ContextResponse(ctx) 1780 resp.Service = service 1781 req := goa.ContextRequest(ctx) 1782 req.Request = r 1783 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1784 headerParam := req.Header["Param"] 1785 if len(headerParam) > 0 { 1786 rawParam := headerParam[0] 1787 req.Params["param"] = []string{rawParam} 1788 rctx.Param = &rawParam 1789 } 1790 paramParam := req.Params["param"] 1791 if len(paramParam) > 0 { 1792 rawParam := paramParam[0] 1793 rctx.Param = &rawParam 1794 } 1795 return &rctx, err 1796 } 1797 ` 1798 1799 numContext = ` 1800 type ListBottleContext struct { 1801 context.Context 1802 *goa.ResponseData 1803 *goa.RequestData 1804 Param *float64 1805 } 1806 ` 1807 1808 numContextFactory = ` 1809 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1810 var err error 1811 resp := goa.ContextResponse(ctx) 1812 resp.Service = service 1813 req := goa.ContextRequest(ctx) 1814 req.Request = r 1815 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1816 paramParam := req.Params["param"] 1817 if len(paramParam) > 0 { 1818 rawParam := paramParam[0] 1819 if param, err2 := strconv.ParseFloat(rawParam, 64); err2 == nil { 1820 tmp1 := ¶m 1821 rctx.Param = tmp1 1822 } else { 1823 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "number")) 1824 } 1825 } 1826 return &rctx, err 1827 } 1828 ` 1829 1830 numNonOptionalContext = ` 1831 type ListBottleContext struct { 1832 context.Context 1833 *goa.ResponseData 1834 *goa.RequestData 1835 Param float64 1836 } 1837 ` 1838 1839 numDefaultContextFactory = ` 1840 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1841 var err error 1842 resp := goa.ContextResponse(ctx) 1843 resp.Service = service 1844 req := goa.ContextRequest(ctx) 1845 req.Request = r 1846 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1847 paramParam := req.Params["param"] 1848 if len(paramParam) == 0 { 1849 rctx.Param = 2.300000 1850 } else { 1851 rawParam := paramParam[0] 1852 if param, err2 := strconv.ParseFloat(rawParam, 64); err2 == nil { 1853 rctx.Param = param 1854 } else { 1855 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "number")) 1856 } 1857 } 1858 return &rctx, err 1859 } 1860 ` 1861 1862 numRequiredContextFactory = ` 1863 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1864 var err error 1865 resp := goa.ContextResponse(ctx) 1866 resp.Service = service 1867 req := goa.ContextRequest(ctx) 1868 req.Request = r 1869 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1870 paramParam := req.Params["param"] 1871 if len(paramParam) == 0 { 1872 err = goa.MergeErrors(err, goa.MissingParamError("param")) 1873 } else { 1874 rawParam := paramParam[0] 1875 if param, err2 := strconv.ParseFloat(rawParam, 64); err2 == nil { 1876 rctx.Param = param 1877 } else { 1878 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "number")) 1879 } 1880 } 1881 return &rctx, err 1882 } 1883 ` 1884 1885 boolContext = ` 1886 type ListBottleContext struct { 1887 context.Context 1888 *goa.ResponseData 1889 *goa.RequestData 1890 Param *bool 1891 } 1892 ` 1893 1894 boolContextFactory = ` 1895 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1896 var err error 1897 resp := goa.ContextResponse(ctx) 1898 resp.Service = service 1899 req := goa.ContextRequest(ctx) 1900 req.Request = r 1901 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1902 paramParam := req.Params["param"] 1903 if len(paramParam) > 0 { 1904 rawParam := paramParam[0] 1905 if param, err2 := strconv.ParseBool(rawParam); err2 == nil { 1906 tmp1 := ¶m 1907 rctx.Param = tmp1 1908 } else { 1909 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "boolean")) 1910 } 1911 } 1912 return &rctx, err 1913 } 1914 ` 1915 1916 boolNonOptionalContext = ` 1917 type ListBottleContext struct { 1918 context.Context 1919 *goa.ResponseData 1920 *goa.RequestData 1921 Param bool 1922 } 1923 ` 1924 1925 boolDefaultContextFactory = ` 1926 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1927 var err error 1928 resp := goa.ContextResponse(ctx) 1929 resp.Service = service 1930 req := goa.ContextRequest(ctx) 1931 req.Request = r 1932 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1933 paramParam := req.Params["param"] 1934 if len(paramParam) == 0 { 1935 rctx.Param = true 1936 } else { 1937 rawParam := paramParam[0] 1938 if param, err2 := strconv.ParseBool(rawParam); err2 == nil { 1939 rctx.Param = param 1940 } else { 1941 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "boolean")) 1942 } 1943 } 1944 return &rctx, err 1945 } 1946 ` 1947 1948 boolRequiredContextFactory = ` 1949 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1950 var err error 1951 resp := goa.ContextResponse(ctx) 1952 resp.Service = service 1953 req := goa.ContextRequest(ctx) 1954 req.Request = r 1955 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1956 paramParam := req.Params["param"] 1957 if len(paramParam) == 0 { 1958 err = goa.MergeErrors(err, goa.MissingParamError("param")) 1959 } else { 1960 rawParam := paramParam[0] 1961 if param, err2 := strconv.ParseBool(rawParam); err2 == nil { 1962 rctx.Param = param 1963 } else { 1964 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "boolean")) 1965 } 1966 } 1967 return &rctx, err 1968 } 1969 ` 1970 1971 arrayContext = ` 1972 type ListBottleContext struct { 1973 context.Context 1974 *goa.ResponseData 1975 *goa.RequestData 1976 Param []string 1977 } 1978 ` 1979 1980 arrayContextFactory = ` 1981 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1982 var err error 1983 resp := goa.ContextResponse(ctx) 1984 resp.Service = service 1985 req := goa.ContextRequest(ctx) 1986 req.Request = r 1987 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1988 paramParam := req.Params["param"] 1989 if len(paramParam) > 0 { 1990 params := paramParam 1991 rctx.Param = params 1992 } 1993 return &rctx, err 1994 } 1995 ` 1996 1997 arrayParamContextFactory = ` 1998 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1999 var err error 2000 resp := goa.ContextResponse(ctx) 2001 resp.Service = service 2002 req := goa.ContextRequest(ctx) 2003 req.Request = r 2004 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2005 paramParam := req.Params["param"] 2006 if len(paramParam) > 0 { 2007 params := paramParam 2008 rctx.Param = params 2009 } 2010 return &rctx, err 2011 } 2012 ` 2013 2014 arrayDefaultContextFactory = ` 2015 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2016 var err error 2017 resp := goa.ContextResponse(ctx) 2018 resp.Service = service 2019 req := goa.ContextRequest(ctx) 2020 req.Request = r 2021 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2022 paramParam := req.Params["param"] 2023 if len(paramParam) == 0 { 2024 rctx.Param = []string{"foo", "bar", "baz"} 2025 } else { 2026 params := paramParam 2027 rctx.Param = params 2028 } 2029 return &rctx, err 2030 } 2031 ` 2032 2033 arrayRequiredContextFactory = ` 2034 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2035 var err error 2036 resp := goa.ContextResponse(ctx) 2037 resp.Service = service 2038 req := goa.ContextRequest(ctx) 2039 req.Request = r 2040 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2041 paramParam := req.Params["param"] 2042 if len(paramParam) == 0 { 2043 err = goa.MergeErrors(err, goa.MissingParamError("param")) 2044 } else { 2045 params := paramParam 2046 rctx.Param = params 2047 } 2048 return &rctx, err 2049 } 2050 ` 2051 2052 intArrayContext = ` 2053 type ListBottleContext struct { 2054 context.Context 2055 *goa.ResponseData 2056 *goa.RequestData 2057 Param []int 2058 } 2059 ` 2060 2061 intArrayContextFactory = ` 2062 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2063 var err error 2064 resp := goa.ContextResponse(ctx) 2065 resp.Service = service 2066 req := goa.ContextRequest(ctx) 2067 req.Request = r 2068 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2069 paramParam := req.Params["param"] 2070 if len(paramParam) > 0 { 2071 params := make([]int, len(paramParam)) 2072 for i, rawParam := range paramParam { 2073 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 2074 params[i] = param 2075 } else { 2076 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 2077 } 2078 } 2079 rctx.Param = params 2080 } 2081 return &rctx, err 2082 } 2083 ` 2084 2085 intArrayDefaultContextFactory = ` 2086 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2087 var err error 2088 resp := goa.ContextResponse(ctx) 2089 resp.Service = service 2090 req := goa.ContextRequest(ctx) 2091 req.Request = r 2092 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2093 paramParam := req.Params["param"] 2094 if len(paramParam) == 0 { 2095 rctx.Param = []int{1, 1, 2, 3, 5, 8} 2096 } else { 2097 params := make([]int, len(paramParam)) 2098 for i, rawParam := range paramParam { 2099 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 2100 params[i] = param 2101 } else { 2102 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 2103 } 2104 } 2105 rctx.Param = params 2106 } 2107 return &rctx, err 2108 } 2109 ` 2110 2111 intArrayRequiredContextFactory = ` 2112 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2113 var err error 2114 resp := goa.ContextResponse(ctx) 2115 resp.Service = service 2116 req := goa.ContextRequest(ctx) 2117 req.Request = r 2118 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2119 paramParam := req.Params["param"] 2120 if len(paramParam) == 0 { 2121 err = goa.MergeErrors(err, goa.MissingParamError("param")) 2122 } else { 2123 params := make([]int, len(paramParam)) 2124 for i, rawParam := range paramParam { 2125 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 2126 params[i] = param 2127 } else { 2128 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 2129 } 2130 } 2131 rctx.Param = params 2132 } 2133 return &rctx, err 2134 } 2135 ` 2136 2137 resContext = ` 2138 type ListBottleContext struct { 2139 context.Context 2140 *goa.ResponseData 2141 *goa.RequestData 2142 Int *int 2143 } 2144 ` 2145 2146 resContextFactory = ` 2147 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2148 var err error 2149 resp := goa.ContextResponse(ctx) 2150 resp.Service = service 2151 req := goa.ContextRequest(ctx) 2152 req.Request = r 2153 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2154 paramInt := req.Params["int"] 2155 if len(paramInt) > 0 { 2156 rawInt := paramInt[0] 2157 if int_, err2 := strconv.Atoi(rawInt); err2 == nil { 2158 tmp2 := int_ 2159 tmp1 := &tmp2 2160 rctx.Int = tmp1 2161 } else { 2162 err = goa.MergeErrors(err, goa.InvalidParamTypeError("int", rawInt, "integer")) 2163 } 2164 } 2165 return &rctx, err 2166 } 2167 ` 2168 2169 requiredContext = ` 2170 type ListBottleContext struct { 2171 context.Context 2172 *goa.ResponseData 2173 *goa.RequestData 2174 Int int 2175 } 2176 ` 2177 2178 requiredContextFactory = ` 2179 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2180 var err error 2181 resp := goa.ContextResponse(ctx) 2182 resp.Service = service 2183 req := goa.ContextRequest(ctx) 2184 req.Request = r 2185 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2186 paramInt := req.Params["int"] 2187 if len(paramInt) == 0 { 2188 err = goa.MergeErrors(err, goa.MissingParamError("int")) 2189 } else { 2190 rawInt := paramInt[0] 2191 if int_, err2 := strconv.Atoi(rawInt); err2 == nil { 2192 rctx.Int = int_ 2193 } else { 2194 err = goa.MergeErrors(err, goa.InvalidParamTypeError("int", rawInt, "integer")) 2195 } 2196 } 2197 return &rctx, err 2198 } 2199 ` 2200 2201 customContext = ` 2202 type ListBottleContext struct { 2203 context.Context 2204 *goa.ResponseData 2205 *goa.RequestData 2206 Custom *int 2207 } 2208 ` 2209 2210 customContextFactory = ` 2211 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2212 var err error 2213 resp := goa.ContextResponse(ctx) 2214 resp.Service = service 2215 req := goa.ContextRequest(ctx) 2216 req.Request = r 2217 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2218 paramInt := req.Params["int"] 2219 if len(paramInt) > 0 { 2220 rawInt := paramInt[0] 2221 if int_, err2 := strconv.Atoi(rawInt); err2 == nil { 2222 tmp2 := int_ 2223 tmp1 := &tmp2 2224 rctx.Custom = tmp1 2225 } else { 2226 err = goa.MergeErrors(err, goa.InvalidParamTypeError("int", rawInt, "integer")) 2227 } 2228 } 2229 return &rctx, err 2230 } 2231 ` 2232 2233 payloadContext = ` 2234 type ListBottleContext struct { 2235 context.Context 2236 *goa.ResponseData 2237 *goa.RequestData 2238 Payload ListBottlePayload 2239 } 2240 ` 2241 2242 payloadContextFactory = ` 2243 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2244 var err error 2245 resp := goa.ContextResponse(ctx) 2246 resp.Service = service 2247 req := goa.ContextRequest(ctx) 2248 req.Request = r 2249 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2250 return &rctx, err 2251 } 2252 ` 2253 payloadObjContext = ` 2254 type ListBottleContext struct { 2255 context.Context 2256 *goa.ResponseData 2257 *goa.RequestData 2258 Payload *ListBottlePayload 2259 } 2260 ` 2261 2262 payloadObjUnmarshal = ` 2263 func unmarshalListBottlePayload(ctx context.Context, service *goa.Service, req *http.Request) error { 2264 payload := &listBottlePayload{} 2265 if err := service.DecodeRequest(req, payload); err != nil { 2266 return err 2267 } 2268 if err := payload.Validate(); err != nil { 2269 // Initialize payload with private data structure so it can be logged 2270 goa.ContextRequest(ctx).Payload = payload 2271 return err 2272 } 2273 goa.ContextRequest(ctx).Payload = payload.Publicize() 2274 return nil 2275 } 2276 ` 2277 payloadNoValidationsObjUnmarshal = ` 2278 func unmarshalListBottlePayload(ctx context.Context, service *goa.Service, req *http.Request) error { 2279 payload := &listBottlePayload{} 2280 if err := service.DecodeRequest(req, payload); err != nil { 2281 return err 2282 } 2283 goa.ContextRequest(ctx).Payload = payload.Publicize() 2284 return nil 2285 } 2286 ` 2287 2288 simpleFileServer = `// PublicController is the controller interface for the Public actions. 2289 type PublicController interface { 2290 goa.Muxer 2291 goa.FileServer 2292 } 2293 ` 2294 2295 fileServerOptionsHandler = `service.Mux.Handle("OPTIONS", "/public/star\\*star/*filepath", ctrl.MuxHandler("preflight", handlePublicOrigin(cors.HandlePreflight()), nil))` 2296 2297 simpleController = `// BottlesController is the controller interface for the Bottles actions. 2298 type BottlesController interface { 2299 goa.Muxer 2300 List(*ListBottleContext) error 2301 } 2302 ` 2303 2304 originsIntegration = `} 2305 h = handleBottlesOrigin(h) 2306 service.Mux.Handle` 2307 2308 originsHandler = `// handleBottlesOrigin applies the CORS response headers corresponding to the origin. 2309 func handleBottlesOrigin(h goa.Handler) goa.Handler { 2310 2311 return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2312 origin := req.Header.Get("Origin") 2313 if origin == "" { 2314 // Not a CORS request 2315 return h(ctx, rw, req) 2316 } 2317 if cors.MatchOrigin(origin, "here.example.com") { 2318 ctx = goa.WithLogContext(ctx, "origin", origin) 2319 rw.Header().Set("Access-Control-Allow-Origin", origin) 2320 rw.Header().Set("Vary", "Origin") 2321 rw.Header().Set("Access-Control-Expose-Headers", "X-Three") 2322 rw.Header().Set("Access-Control-Allow-Credentials", "true") 2323 if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" { 2324 // We are handling a preflight request 2325 rw.Header().Set("Access-Control-Allow-Methods", "GET, POST") 2326 rw.Header().Set("Access-Control-Allow-Headers", "X-One, X-Two") 2327 } 2328 return h(ctx, rw, req) 2329 } 2330 if cors.MatchOrigin(origin, "there.example.com") { 2331 ctx = goa.WithLogContext(ctx, "origin", origin) 2332 rw.Header().Set("Access-Control-Allow-Origin", origin) 2333 rw.Header().Set("Vary", "Origin") 2334 rw.Header().Set("Access-Control-Allow-Credentials", "false") 2335 if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" { 2336 // We are handling a preflight request 2337 rw.Header().Set("Access-Control-Allow-Methods", "*") 2338 rw.Header().Set("Access-Control-Allow-Headers", "*") 2339 } 2340 return h(ctx, rw, req) 2341 } 2342 2343 return h(ctx, rw, req) 2344 } 2345 } 2346 ` 2347 2348 regexpOriginsHandler = `// handleBottlesOrigin applies the CORS response headers corresponding to the origin. 2349 func handleBottlesOrigin(h goa.Handler) goa.Handler { 2350 spec0 := regexp.MustCompile("[here|there].example.com") 2351 2352 return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2353 origin := req.Header.Get("Origin") 2354 if origin == "" { 2355 // Not a CORS request 2356 return h(ctx, rw, req) 2357 } 2358 if cors.MatchOriginRegexp(origin, spec0) { 2359 ctx = goa.WithLogContext(ctx, "origin", origin) 2360 rw.Header().Set("Access-Control-Allow-Origin", origin) 2361 rw.Header().Set("Vary", "Origin") 2362 rw.Header().Set("Access-Control-Expose-Headers", "X-Three") 2363 rw.Header().Set("Access-Control-Allow-Credentials", "true") 2364 if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" { 2365 // We are handling a preflight request 2366 rw.Header().Set("Access-Control-Allow-Methods", "GET, POST") 2367 rw.Header().Set("Access-Control-Allow-Headers", "X-One, X-Two") 2368 } 2369 return h(ctx, rw, req) 2370 } 2371 if cors.MatchOrigin(origin, "there.example.com") { 2372 ctx = goa.WithLogContext(ctx, "origin", origin) 2373 rw.Header().Set("Access-Control-Allow-Origin", origin) 2374 rw.Header().Set("Vary", "Origin") 2375 rw.Header().Set("Access-Control-Allow-Credentials", "false") 2376 if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" { 2377 // We are handling a preflight request 2378 rw.Header().Set("Access-Control-Allow-Methods", "*") 2379 rw.Header().Set("Access-Control-Allow-Headers", "*") 2380 } 2381 return h(ctx, rw, req) 2382 } 2383 2384 return h(ctx, rw, req) 2385 } 2386 } 2387 ` 2388 2389 encoderController = ` 2390 // MountBottlesController "mounts" a Bottles resource controller on the given service. 2391 func MountBottlesController(service *goa.Service, ctrl BottlesController) { 2392 initService(service) 2393 var h goa.Handler 2394 2395 h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2396 // Check if there was an error loading the request 2397 if err := goa.ContextError(ctx); err != nil { 2398 return err 2399 } 2400 // Build the context 2401 rctx, err := NewListBottleContext(ctx, req, service) 2402 if err != nil { 2403 return err 2404 } 2405 return ctrl.List(rctx) 2406 } 2407 service.Mux.Handle("GET", "/accounts/:accountID/bottles", ctrl.MuxHandler("list", h, nil)) 2408 service.LogInfo("mount", "ctrl", "Bottles", "action", "List", "route", "GET /accounts/:accountID/bottles") 2409 } 2410 ` 2411 2412 simpleMount = `func MountBottlesController(service *goa.Service, ctrl BottlesController) { 2413 initService(service) 2414 var h goa.Handler 2415 2416 h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2417 // Check if there was an error loading the request 2418 if err := goa.ContextError(ctx); err != nil { 2419 return err 2420 } 2421 // Build the context 2422 rctx, err := NewListBottleContext(ctx, req, service) 2423 if err != nil { 2424 return err 2425 } 2426 return ctrl.List(rctx) 2427 } 2428 service.Mux.Handle("GET", "/accounts/:accountID/bottles", ctrl.MuxHandler("list", h, nil)) 2429 service.LogInfo("mount", "ctrl", "Bottles", "action", "List", "route", "GET /accounts/:accountID/bottles") 2430 } 2431 ` 2432 2433 multiController = `// BottlesController is the controller interface for the Bottles actions. 2434 type BottlesController interface { 2435 goa.Muxer 2436 List(*ListBottleContext) error 2437 Show(*ShowBottleContext) error 2438 } 2439 ` 2440 2441 multiMount = `func MountBottlesController(service *goa.Service, ctrl BottlesController) { 2442 initService(service) 2443 var h goa.Handler 2444 2445 h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2446 // Check if there was an error loading the request 2447 if err := goa.ContextError(ctx); err != nil { 2448 return err 2449 } 2450 // Build the context 2451 rctx, err := NewListBottleContext(ctx, req, service) 2452 if err != nil { 2453 return err 2454 } 2455 return ctrl.List(rctx) 2456 } 2457 service.Mux.Handle("GET", "/accounts/:accountID/bottles", ctrl.MuxHandler("list", h, nil)) 2458 service.LogInfo("mount", "ctrl", "Bottles", "action", "List", "route", "GET /accounts/:accountID/bottles") 2459 2460 h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2461 // Check if there was an error loading the request 2462 if err := goa.ContextError(ctx); err != nil { 2463 return err 2464 } 2465 // Build the context 2466 rctx, err := NewShowBottleContext(ctx, req, service) 2467 if err != nil { 2468 return err 2469 } 2470 return ctrl.Show(rctx) 2471 } 2472 service.Mux.Handle("GET", "/accounts/:accountID/bottles/:id", ctrl.MuxHandler("show", h, nil)) 2473 service.LogInfo("mount", "ctrl", "Bottles", "action", "Show", "route", "GET /accounts/:accountID/bottles/:id") 2474 } 2475 ` 2476 2477 simpleResourceHref = `func BottleHref(id interface{}) string { 2478 paramid := strings.TrimLeftFunc(fmt.Sprintf("%v", id), func(r rune) bool { return r == '/' }) 2479 return fmt.Sprintf("/bottles/%v", paramid) 2480 } 2481 ` 2482 noParamHref = `func BottleHref() string { 2483 return "/bottles" 2484 } 2485 ` 2486 2487 simpleUserType = `// simplePayload user type. 2488 type simplePayload struct { 2489 Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + "`" + ` 2490 } 2491 2492 2493 2494 // Publicize creates SimplePayload from simplePayload 2495 func (ut *simplePayload) Publicize() *SimplePayload { 2496 var pub SimplePayload 2497 if ut.Name != nil { 2498 pub.Name = ut.Name 2499 } 2500 return &pub 2501 } 2502 2503 // SimplePayload user type. 2504 type SimplePayload struct { 2505 Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + "`" + ` 2506 } 2507 ` 2508 2509 userTypeIncludingHash = `// complexPayload user type. 2510 type complexPayload struct { 2511 Misc map[int]*miscPayload ` + "`" + `form:"misc,omitempty" json:"misc,omitempty" xml:"misc,omitempty"` + "`" + ` 2512 Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + "`" + ` 2513 } 2514 2515 2516 2517 // Publicize creates ComplexPayload from complexPayload 2518 func (ut *complexPayload) Publicize() *ComplexPayload { 2519 var pub ComplexPayload 2520 if ut.Misc != nil { 2521 pub.Misc = make(map[int]*MiscPayload, len(ut.Misc)) 2522 for k2, v2 := range ut.Misc { 2523 pubk2 := k2 2524 var pubv2 *MiscPayload 2525 if v2 != nil { 2526 pubv2 = v2.Publicize() 2527 } 2528 pub.Misc[pubk2] = pubv2 2529 } 2530 } 2531 if ut.Name != nil { 2532 pub.Name = ut.Name 2533 } 2534 return &pub 2535 } 2536 2537 // ComplexPayload user type. 2538 type ComplexPayload struct { 2539 Misc map[int]*MiscPayload ` + "`" + `form:"misc,omitempty" json:"misc,omitempty" xml:"misc,omitempty"` + "`" + ` 2540 Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" xml:"name,omitempty"` + "`" + ` 2541 } 2542 ` 2543 )