github.com/blp1526/goa@v1.4.0/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 multipart bool 998 var actions, verbs, paths, contexts, unmarshals []string 999 var payloads []*design.UserTypeDefinition 1000 var encoders, decoders []*genapp.EncoderTemplateData 1001 var origins []*design.CORSDefinition 1002 1003 var data []*genapp.ControllerTemplateData 1004 1005 BeforeEach(func() { 1006 multipart = false 1007 actions = nil 1008 verbs = nil 1009 paths = nil 1010 contexts = nil 1011 unmarshals = nil 1012 payloads = nil 1013 encoders = nil 1014 decoders = nil 1015 origins = nil 1016 }) 1017 1018 JustBeforeEach(func() { 1019 codegen.TempCount = 0 1020 api := &design.APIDefinition{} 1021 d := &genapp.ControllerTemplateData{ 1022 Resource: "Bottles", 1023 Origins: origins, 1024 } 1025 as := make([]map[string]interface{}, len(actions)) 1026 for i, a := range actions { 1027 var unmarshal string 1028 var payload *design.UserTypeDefinition 1029 if i < len(unmarshals) { 1030 unmarshal = unmarshals[i] 1031 } 1032 if i < len(payloads) { 1033 payload = payloads[i] 1034 } 1035 as[i] = map[string]interface{}{ 1036 "Name": codegen.Goify(a, true), 1037 "DesignName": a, 1038 "Routes": []*design.RouteDefinition{ 1039 { 1040 Verb: verbs[i], 1041 Path: paths[i], 1042 }}, 1043 "Context": contexts[i], 1044 "Unmarshal": unmarshal, 1045 "Payload": payload, 1046 "PayloadMultipart": multipart, 1047 } 1048 } 1049 if len(as) > 0 { 1050 d.API = api 1051 d.Actions = as 1052 d.Encoders = encoders 1053 d.Decoders = decoders 1054 data = []*genapp.ControllerTemplateData{d} 1055 } else { 1056 data = nil 1057 } 1058 }) 1059 1060 Context("with missing data", func() { 1061 It("returns an empty string", func() { 1062 err := writer.Execute(data) 1063 Ω(err).ShouldNot(HaveOccurred()) 1064 b, err := ioutil.ReadFile(filename) 1065 Ω(err).ShouldNot(HaveOccurred()) 1066 written := string(b) 1067 Ω(written).Should(BeEmpty()) 1068 }) 1069 }) 1070 1071 Context("with a simple controller", func() { 1072 BeforeEach(func() { 1073 actions = []string{"list"} 1074 verbs = []string{"GET"} 1075 paths = []string{"/accounts/:accountID/bottles"} 1076 contexts = []string{"ListBottleContext"} 1077 }) 1078 1079 It("writes the controller code", func() { 1080 err := writer.Execute(data) 1081 Ω(err).ShouldNot(HaveOccurred()) 1082 b, err := ioutil.ReadFile(filename) 1083 Ω(err).ShouldNot(HaveOccurred()) 1084 written := string(b) 1085 Ω(written).ShouldNot(BeEmpty()) 1086 Ω(written).Should(ContainSubstring(simpleController)) 1087 Ω(written).Should(ContainSubstring(simpleMount)) 1088 }) 1089 }) 1090 1091 Context("with actions that take a payload", func() { 1092 BeforeEach(func() { 1093 actions = []string{"list"} 1094 verbs = []string{"GET"} 1095 paths = []string{"/accounts/:accountID/bottles"} 1096 contexts = []string{"ListBottleContext"} 1097 unmarshals = []string{"unmarshalListBottlePayload"} 1098 payloads = []*design.UserTypeDefinition{ 1099 { 1100 TypeName: "ListBottlePayload", 1101 AttributeDefinition: &design.AttributeDefinition{ 1102 Type: design.Object{ 1103 "id": &design.AttributeDefinition{ 1104 Type: design.String, 1105 }, 1106 }, 1107 }, 1108 }, 1109 } 1110 }) 1111 1112 It("writes the payload unmarshal function", func() { 1113 err := writer.Execute(data) 1114 Ω(err).ShouldNot(HaveOccurred()) 1115 b, err := ioutil.ReadFile(filename) 1116 Ω(err).ShouldNot(HaveOccurred()) 1117 written := string(b) 1118 Ω(written).Should(ContainSubstring(payloadNoValidationsObjUnmarshal)) 1119 }) 1120 }) 1121 Context("with actions that take a payload with a required validation", func() { 1122 BeforeEach(func() { 1123 actions = []string{"list"} 1124 required := &dslengine.ValidationDefinition{ 1125 Required: []string{"id"}, 1126 } 1127 verbs = []string{"GET"} 1128 paths = []string{"/accounts/:accountID/bottles"} 1129 contexts = []string{"ListBottleContext"} 1130 unmarshals = []string{"unmarshalListBottlePayload"} 1131 payloads = []*design.UserTypeDefinition{ 1132 { 1133 TypeName: "ListBottlePayload", 1134 AttributeDefinition: &design.AttributeDefinition{ 1135 Type: design.Object{ 1136 "id": &design.AttributeDefinition{ 1137 Type: design.String, 1138 }, 1139 }, 1140 Validation: required, 1141 }, 1142 }, 1143 } 1144 }) 1145 1146 It("writes the payload unmarshal function", func() { 1147 err := writer.Execute(data) 1148 Ω(err).ShouldNot(HaveOccurred()) 1149 b, err := ioutil.ReadFile(filename) 1150 Ω(err).ShouldNot(HaveOccurred()) 1151 written := string(b) 1152 Ω(written).Should(ContainSubstring(payloadObjUnmarshal)) 1153 }) 1154 }) 1155 1156 Context("with actions that take a multipart payload", func() { 1157 BeforeEach(func() { 1158 actions = []string{"list"} 1159 required := &dslengine.ValidationDefinition{ 1160 Required: []string{"id"}, 1161 } 1162 verbs = []string{"GET"} 1163 paths = []string{"/accounts/:accountID/bottles"} 1164 contexts = []string{"ListBottleContext"} 1165 unmarshals = []string{"unmarshalListBottlePayload"} 1166 payloads = []*design.UserTypeDefinition{ 1167 { 1168 TypeName: "ListBottlePayload", 1169 AttributeDefinition: &design.AttributeDefinition{ 1170 Type: design.Object{ 1171 "id": &design.AttributeDefinition{ 1172 Type: design.String, 1173 }, 1174 "icon": &design.AttributeDefinition{ 1175 Type: design.File, 1176 }, 1177 }, 1178 Validation: required, 1179 }, 1180 }, 1181 } 1182 multipart = true 1183 }) 1184 1185 It("writes the payload unmarshal function", func() { 1186 err := writer.Execute(data) 1187 Ω(err).ShouldNot(HaveOccurred()) 1188 b, err := ioutil.ReadFile(filename) 1189 Ω(err).ShouldNot(HaveOccurred()) 1190 written := string(b) 1191 Ω(written).Should(ContainSubstring(payloadMultipartObjUnmarshal)) 1192 }) 1193 }) 1194 1195 Context("with multiple controllers", func() { 1196 BeforeEach(func() { 1197 actions = []string{"list", "show"} 1198 verbs = []string{"GET", "GET"} 1199 paths = []string{"/accounts/:accountID/bottles", "/accounts/:accountID/bottles/:id"} 1200 contexts = []string{"ListBottleContext", "ShowBottleContext"} 1201 }) 1202 1203 It("writes the controllers code", func() { 1204 err := writer.Execute(data) 1205 Ω(err).ShouldNot(HaveOccurred()) 1206 b, err := ioutil.ReadFile(filename) 1207 Ω(err).ShouldNot(HaveOccurred()) 1208 written := string(b) 1209 Ω(written).ShouldNot(BeEmpty()) 1210 Ω(written).Should(ContainSubstring(multiController)) 1211 Ω(written).Should(ContainSubstring(multiMount)) 1212 }) 1213 }) 1214 1215 Context("with encoder and decoder maps", func() { 1216 BeforeEach(func() { 1217 actions = []string{"list"} 1218 verbs = []string{"GET"} 1219 paths = []string{"/accounts/:accountID/bottles"} 1220 contexts = []string{"ListBottleContext"} 1221 encoders = []*genapp.EncoderTemplateData{ 1222 { 1223 PackageName: "goa", 1224 Function: "NewEncoder", 1225 MIMETypes: []string{"application/json"}, 1226 }, 1227 } 1228 decoders = []*genapp.EncoderTemplateData{ 1229 { 1230 PackageName: "goa", 1231 Function: "NewDecoder", 1232 MIMETypes: []string{"application/json"}, 1233 }, 1234 } 1235 }) 1236 1237 It("writes the controllers code", func() { 1238 err := writer.Execute(data) 1239 Ω(err).ShouldNot(HaveOccurred()) 1240 b, err := ioutil.ReadFile(filename) 1241 Ω(err).ShouldNot(HaveOccurred()) 1242 written := string(b) 1243 Ω(written).ShouldNot(BeEmpty()) 1244 Ω(written).Should(ContainSubstring(encoderController)) 1245 }) 1246 }) 1247 1248 Context("with multiple origins", func() { 1249 BeforeEach(func() { 1250 actions = []string{"list"} 1251 verbs = []string{"GET"} 1252 paths = []string{"/accounts"} 1253 contexts = []string{"ListBottleContext"} 1254 origins = []*design.CORSDefinition{ 1255 { 1256 Origin: "here.example.com", 1257 Headers: []string{"X-One", "X-Two"}, 1258 Methods: []string{"GET", "POST"}, 1259 Exposed: []string{"X-Three"}, 1260 Credentials: true, 1261 }, 1262 { 1263 Origin: "there.example.com", 1264 Headers: []string{"*"}, 1265 Methods: []string{"*"}, 1266 }, 1267 } 1268 1269 }) 1270 1271 It("writes the controller code", func() { 1272 err := writer.Execute(data) 1273 Ω(err).ShouldNot(HaveOccurred()) 1274 b, err := ioutil.ReadFile(filename) 1275 Ω(err).ShouldNot(HaveOccurred()) 1276 written := string(b) 1277 Ω(written).ShouldNot(BeEmpty()) 1278 Ω(written).Should(ContainSubstring(originsIntegration)) 1279 Ω(written).Should(ContainSubstring(originsHandler)) 1280 }) 1281 }) 1282 1283 Context("with regexp origins", func() { 1284 BeforeEach(func() { 1285 actions = []string{"list"} 1286 verbs = []string{"GET"} 1287 paths = []string{"/accounts"} 1288 contexts = []string{"ListBottleContext"} 1289 origins = []*design.CORSDefinition{ 1290 { 1291 Origin: "[here|there].example.com", 1292 Headers: []string{"X-One", "X-Two"}, 1293 Methods: []string{"GET", "POST"}, 1294 Exposed: []string{"X-Three"}, 1295 Credentials: true, 1296 Regexp: true, 1297 }, 1298 { 1299 Origin: "there.example.com", 1300 Headers: []string{"*"}, 1301 Methods: []string{"*"}, 1302 }, 1303 } 1304 1305 }) 1306 1307 It("writes the controller code", func() { 1308 err := writer.Execute(data) 1309 Ω(err).ShouldNot(HaveOccurred()) 1310 b, err := ioutil.ReadFile(filename) 1311 Ω(err).ShouldNot(HaveOccurred()) 1312 written := string(b) 1313 Ω(written).ShouldNot(BeEmpty()) 1314 Ω(written).Should(ContainSubstring(originsIntegration)) 1315 Ω(written).Should(ContainSubstring(regexpOriginsHandler)) 1316 }) 1317 }) 1318 1319 }) 1320 }) 1321 }) 1322 1323 var _ = Describe("HrefWriter", func() { 1324 var writer *genapp.ResourcesWriter 1325 var workspace *codegen.Workspace 1326 var filename string 1327 1328 BeforeEach(func() { 1329 var err error 1330 workspace, err = codegen.NewWorkspace("test") 1331 Ω(err).ShouldNot(HaveOccurred()) 1332 pkg, err := workspace.NewPackage("controllers") 1333 Ω(err).ShouldNot(HaveOccurred()) 1334 src, err := pkg.CreateSourceFile("test.go") 1335 Ω(err).ShouldNot(HaveOccurred()) 1336 defer src.Close() 1337 filename = src.Abs() 1338 }) 1339 1340 JustBeforeEach(func() { 1341 var err error 1342 writer, err = genapp.NewResourcesWriter(filename) 1343 Ω(err).ShouldNot(HaveOccurred()) 1344 }) 1345 1346 AfterEach(func() { 1347 workspace.Delete() 1348 }) 1349 1350 Context("correctly configured", func() { 1351 Context("with data", func() { 1352 var canoTemplate string 1353 var canoParams []string 1354 var mediaType *design.MediaTypeDefinition 1355 1356 var data *genapp.ResourceData 1357 1358 BeforeEach(func() { 1359 mediaType = nil 1360 canoTemplate = "" 1361 canoParams = nil 1362 data = nil 1363 }) 1364 1365 JustBeforeEach(func() { 1366 data = &genapp.ResourceData{ 1367 Name: "Bottle", 1368 Identifier: "vnd.acme.com/resources", 1369 Description: "A bottle resource", 1370 Type: mediaType, 1371 CanonicalTemplate: canoTemplate, 1372 CanonicalParams: canoParams, 1373 } 1374 }) 1375 1376 Context("with missing resource type definition", func() { 1377 It("does not return an error", func() { 1378 err := writer.Execute(data) 1379 Ω(err).ShouldNot(HaveOccurred()) 1380 }) 1381 }) 1382 1383 Context("with a string resource", func() { 1384 BeforeEach(func() { 1385 attDef := &design.AttributeDefinition{ 1386 Type: design.String, 1387 } 1388 mediaType = &design.MediaTypeDefinition{ 1389 UserTypeDefinition: &design.UserTypeDefinition{ 1390 AttributeDefinition: attDef, 1391 TypeName: "Bottle", 1392 }, 1393 } 1394 }) 1395 It("does not return an error", func() { 1396 err := writer.Execute(data) 1397 Ω(err).ShouldNot(HaveOccurred()) 1398 }) 1399 }) 1400 1401 Context("with a user type resource", func() { 1402 BeforeEach(func() { 1403 intParam := &design.AttributeDefinition{Type: design.Integer} 1404 strParam := &design.AttributeDefinition{Type: design.String} 1405 dataType := design.Object{ 1406 "int": intParam, 1407 "str": strParam, 1408 } 1409 attDef := &design.AttributeDefinition{ 1410 Type: dataType, 1411 } 1412 mediaType = &design.MediaTypeDefinition{ 1413 UserTypeDefinition: &design.UserTypeDefinition{ 1414 AttributeDefinition: attDef, 1415 TypeName: "Bottle", 1416 }, 1417 } 1418 }) 1419 1420 Context("and a canonical action", func() { 1421 BeforeEach(func() { 1422 canoTemplate = "/bottles/%v" 1423 canoParams = []string{"id"} 1424 }) 1425 1426 It("writes the href method", func() { 1427 err := writer.Execute(data) 1428 Ω(err).ShouldNot(HaveOccurred()) 1429 b, err := ioutil.ReadFile(filename) 1430 Ω(err).ShouldNot(HaveOccurred()) 1431 written := string(b) 1432 Ω(written).ShouldNot(BeEmpty()) 1433 Ω(written).Should(ContainSubstring(simpleResourceHref)) 1434 }) 1435 }) 1436 1437 Context("and a canonical action with no param", func() { 1438 BeforeEach(func() { 1439 canoTemplate = "/bottles" 1440 }) 1441 1442 It("writes the href method", func() { 1443 err := writer.Execute(data) 1444 Ω(err).ShouldNot(HaveOccurred()) 1445 b, err := ioutil.ReadFile(filename) 1446 Ω(err).ShouldNot(HaveOccurred()) 1447 written := string(b) 1448 Ω(written).ShouldNot(BeEmpty()) 1449 Ω(written).Should(ContainSubstring(noParamHref)) 1450 }) 1451 }) 1452 }) 1453 }) 1454 }) 1455 }) 1456 1457 var _ = Describe("UserTypesWriter", func() { 1458 var writer *genapp.UserTypesWriter 1459 var workspace *codegen.Workspace 1460 var filename string 1461 1462 BeforeEach(func() { 1463 var err error 1464 workspace, err = codegen.NewWorkspace("test") 1465 Ω(err).ShouldNot(HaveOccurred()) 1466 pkg, err := workspace.NewPackage("controllers") 1467 Ω(err).ShouldNot(HaveOccurred()) 1468 src, err := pkg.CreateSourceFile("test.go") 1469 Ω(err).ShouldNot(HaveOccurred()) 1470 defer src.Close() 1471 filename = src.Abs() 1472 }) 1473 1474 JustBeforeEach(func() { 1475 var err error 1476 writer, err = genapp.NewUserTypesWriter(filename) 1477 Ω(err).ShouldNot(HaveOccurred()) 1478 }) 1479 1480 AfterEach(func() { 1481 workspace.Delete() 1482 }) 1483 1484 Context("correctly configured", func() { 1485 Context("with data", func() { 1486 var data *design.UserTypeDefinition 1487 var attDef *design.AttributeDefinition 1488 var typeName string 1489 1490 BeforeEach(func() { 1491 data = nil 1492 attDef = nil 1493 typeName = "" 1494 }) 1495 1496 JustBeforeEach(func() { 1497 data = &design.UserTypeDefinition{ 1498 AttributeDefinition: attDef, 1499 TypeName: typeName, 1500 } 1501 }) 1502 1503 Context("with a simple user type", func() { 1504 BeforeEach(func() { 1505 attDef = &design.AttributeDefinition{ 1506 Type: design.Object{ 1507 "name": &design.AttributeDefinition{ 1508 Type: design.String, 1509 }, 1510 }, 1511 } 1512 typeName = "SimplePayload" 1513 }) 1514 It("writes the simple user type code", 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(simpleUserType)) 1522 }) 1523 }) 1524 1525 Context("with a user type including hash", func() { 1526 BeforeEach(func() { 1527 attDef = &design.AttributeDefinition{ 1528 Type: design.Object{ 1529 "name": &design.AttributeDefinition{ 1530 Type: design.String, 1531 }, 1532 "misc": &design.AttributeDefinition{ 1533 Type: &design.Hash{ 1534 KeyType: &design.AttributeDefinition{ 1535 Type: design.Integer, 1536 }, 1537 ElemType: &design.AttributeDefinition{ 1538 Type: &design.UserTypeDefinition{ 1539 AttributeDefinition: &design.AttributeDefinition{ 1540 Type: &design.UserTypeDefinition{ 1541 AttributeDefinition: &design.AttributeDefinition{ 1542 Type: design.Object{}, 1543 }, 1544 TypeName: "Misc", 1545 }, 1546 }, 1547 TypeName: "MiscPayload", 1548 }, 1549 }, 1550 }, 1551 }, 1552 }, 1553 } 1554 typeName = "ComplexPayload" 1555 }) 1556 It("writes the user type including hash", func() { 1557 err := writer.Execute(data) 1558 Ω(err).ShouldNot(HaveOccurred()) 1559 b, err := ioutil.ReadFile(filename) 1560 Ω(err).ShouldNot(HaveOccurred()) 1561 written := string(b) 1562 Ω(written).ShouldNot(BeEmpty()) 1563 Ω(written).Should(ContainSubstring(userTypeIncludingHash)) 1564 }) 1565 }) 1566 }) 1567 }) 1568 }) 1569 1570 const ( 1571 emptyContext = ` 1572 type ListBottleContext struct { 1573 context.Context 1574 *goa.ResponseData 1575 *goa.RequestData 1576 } 1577 ` 1578 1579 emptyContextFactory = ` 1580 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1581 var err error 1582 resp := goa.ContextResponse(ctx) 1583 resp.Service = service 1584 req := goa.ContextRequest(ctx) 1585 req.Request = r 1586 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1587 return &rctx, err 1588 } 1589 ` 1590 1591 intContext = ` 1592 type ListBottleContext struct { 1593 context.Context 1594 *goa.ResponseData 1595 *goa.RequestData 1596 Param *int 1597 } 1598 ` 1599 1600 intContextFactory = ` 1601 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1602 var err error 1603 resp := goa.ContextResponse(ctx) 1604 resp.Service = service 1605 req := goa.ContextRequest(ctx) 1606 req.Request = r 1607 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1608 paramParam := req.Params["param"] 1609 if len(paramParam) > 0 { 1610 rawParam := paramParam[0] 1611 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 1612 tmp2 := param 1613 tmp1 := &tmp2 1614 rctx.Param = tmp1 1615 } else { 1616 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 1617 } 1618 } 1619 return &rctx, err 1620 } 1621 ` 1622 1623 intDefaultContext = ` 1624 type ListBottleContext struct { 1625 context.Context 1626 *goa.ResponseData 1627 *goa.RequestData 1628 Param int 1629 } 1630 ` 1631 1632 intDefaultContextFactory = ` 1633 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1634 var err error 1635 resp := goa.ContextResponse(ctx) 1636 resp.Service = service 1637 req := goa.ContextRequest(ctx) 1638 req.Request = r 1639 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1640 paramParam := req.Params["param"] 1641 if len(paramParam) == 0 { 1642 rctx.Param = 2 1643 } else { 1644 rawParam := paramParam[0] 1645 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 1646 rctx.Param = param 1647 } else { 1648 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 1649 } 1650 } 1651 return &rctx, err 1652 } 1653 ` 1654 1655 intRequiredDefaultContext = ` 1656 type ListBottleContext struct { 1657 context.Context 1658 *goa.ResponseData 1659 *goa.RequestData 1660 Param int 1661 } 1662 ` 1663 1664 intRequiredDefaultContextFactory = ` 1665 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1666 var err error 1667 resp := goa.ContextResponse(ctx) 1668 resp.Service = service 1669 req := goa.ContextRequest(ctx) 1670 req.Request = r 1671 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1672 paramParam := req.Params["param"] 1673 if len(paramParam) == 0 { 1674 rctx.Param = 2 1675 } else { 1676 rawParam := paramParam[0] 1677 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 1678 rctx.Param = param 1679 } else { 1680 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 1681 } 1682 } 1683 return &rctx, err 1684 } 1685 ` 1686 1687 intRequiredContext = ` 1688 type ListBottleContext struct { 1689 context.Context 1690 *goa.ResponseData 1691 *goa.RequestData 1692 Param int 1693 } 1694 ` 1695 intRequiredContextFactory = ` 1696 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1697 var err error 1698 resp := goa.ContextResponse(ctx) 1699 resp.Service = service 1700 req := goa.ContextRequest(ctx) 1701 req.Request = r 1702 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1703 paramParam := req.Params["param"] 1704 if len(paramParam) == 0 { 1705 err = goa.MergeErrors(err, goa.MissingParamError("param")) 1706 } else { 1707 rawParam := paramParam[0] 1708 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 1709 rctx.Param = param 1710 } else { 1711 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 1712 } 1713 } 1714 return &rctx, err 1715 } 1716 ` 1717 1718 strContext = ` 1719 type ListBottleContext struct { 1720 context.Context 1721 *goa.ResponseData 1722 *goa.RequestData 1723 Param *string 1724 } 1725 ` 1726 1727 strContextFactory = ` 1728 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1729 var err error 1730 resp := goa.ContextResponse(ctx) 1731 resp.Service = service 1732 req := goa.ContextRequest(ctx) 1733 req.Request = r 1734 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1735 paramParam := req.Params["param"] 1736 if len(paramParam) > 0 { 1737 rawParam := paramParam[0] 1738 rctx.Param = &rawParam 1739 } 1740 return &rctx, err 1741 } 1742 ` 1743 1744 strNonOptionalContext = ` 1745 type ListBottleContext struct { 1746 context.Context 1747 *goa.ResponseData 1748 *goa.RequestData 1749 Param string 1750 } 1751 ` 1752 1753 strDefaultContextFactory = ` 1754 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1755 var err error 1756 resp := goa.ContextResponse(ctx) 1757 resp.Service = service 1758 req := goa.ContextRequest(ctx) 1759 req.Request = r 1760 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1761 paramParam := req.Params["param"] 1762 if len(paramParam) == 0 { 1763 rctx.Param = "foo" 1764 } else { 1765 rawParam := paramParam[0] 1766 rctx.Param = rawParam 1767 } 1768 return &rctx, err 1769 } 1770 ` 1771 1772 strRequiredContextFactory = ` 1773 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1774 var err error 1775 resp := goa.ContextResponse(ctx) 1776 resp.Service = service 1777 req := goa.ContextRequest(ctx) 1778 req.Request = r 1779 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1780 paramParam := req.Params["param"] 1781 if len(paramParam) == 0 { 1782 err = goa.MergeErrors(err, goa.MissingParamError("param")) 1783 } else { 1784 rawParam := paramParam[0] 1785 rctx.Param = rawParam 1786 } 1787 return &rctx, err 1788 } 1789 ` 1790 1791 strHeaderContext = ` 1792 type ListBottleContext struct { 1793 context.Context 1794 *goa.ResponseData 1795 *goa.RequestData 1796 Header *string 1797 } 1798 ` 1799 1800 strHeaderContextFactory = ` 1801 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1802 var err error 1803 resp := goa.ContextResponse(ctx) 1804 resp.Service = service 1805 req := goa.ContextRequest(ctx) 1806 req.Request = r 1807 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1808 headerHeader := req.Header["Header"] 1809 if len(headerHeader) > 0 { 1810 rawHeader := headerHeader[0] 1811 req.Params["Header"] = []string{rawHeader} 1812 rctx.Header = &rawHeader 1813 } 1814 return &rctx, err 1815 } 1816 ` 1817 1818 strHeaderParamContextFactory = ` 1819 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1820 var err error 1821 resp := goa.ContextResponse(ctx) 1822 resp.Service = service 1823 req := goa.ContextRequest(ctx) 1824 req.Request = r 1825 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1826 headerParam := req.Header["Param"] 1827 if len(headerParam) > 0 { 1828 rawParam := headerParam[0] 1829 req.Params["param"] = []string{rawParam} 1830 rctx.Param = &rawParam 1831 } 1832 paramParam := req.Params["param"] 1833 if len(paramParam) > 0 { 1834 rawParam := paramParam[0] 1835 rctx.Param = &rawParam 1836 } 1837 return &rctx, err 1838 } 1839 ` 1840 1841 numContext = ` 1842 type ListBottleContext struct { 1843 context.Context 1844 *goa.ResponseData 1845 *goa.RequestData 1846 Param *float64 1847 } 1848 ` 1849 1850 numContextFactory = ` 1851 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1852 var err error 1853 resp := goa.ContextResponse(ctx) 1854 resp.Service = service 1855 req := goa.ContextRequest(ctx) 1856 req.Request = r 1857 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1858 paramParam := req.Params["param"] 1859 if len(paramParam) > 0 { 1860 rawParam := paramParam[0] 1861 if param, err2 := strconv.ParseFloat(rawParam, 64); err2 == nil { 1862 tmp1 := ¶m 1863 rctx.Param = tmp1 1864 } else { 1865 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "number")) 1866 } 1867 } 1868 return &rctx, err 1869 } 1870 ` 1871 1872 numNonOptionalContext = ` 1873 type ListBottleContext struct { 1874 context.Context 1875 *goa.ResponseData 1876 *goa.RequestData 1877 Param float64 1878 } 1879 ` 1880 1881 numDefaultContextFactory = ` 1882 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1883 var err error 1884 resp := goa.ContextResponse(ctx) 1885 resp.Service = service 1886 req := goa.ContextRequest(ctx) 1887 req.Request = r 1888 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1889 paramParam := req.Params["param"] 1890 if len(paramParam) == 0 { 1891 rctx.Param = 2.300000 1892 } else { 1893 rawParam := paramParam[0] 1894 if param, err2 := strconv.ParseFloat(rawParam, 64); err2 == nil { 1895 rctx.Param = param 1896 } else { 1897 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "number")) 1898 } 1899 } 1900 return &rctx, err 1901 } 1902 ` 1903 1904 numRequiredContextFactory = ` 1905 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1906 var err error 1907 resp := goa.ContextResponse(ctx) 1908 resp.Service = service 1909 req := goa.ContextRequest(ctx) 1910 req.Request = r 1911 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1912 paramParam := req.Params["param"] 1913 if len(paramParam) == 0 { 1914 err = goa.MergeErrors(err, goa.MissingParamError("param")) 1915 } else { 1916 rawParam := paramParam[0] 1917 if param, err2 := strconv.ParseFloat(rawParam, 64); err2 == nil { 1918 rctx.Param = param 1919 } else { 1920 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "number")) 1921 } 1922 } 1923 return &rctx, err 1924 } 1925 ` 1926 1927 boolContext = ` 1928 type ListBottleContext struct { 1929 context.Context 1930 *goa.ResponseData 1931 *goa.RequestData 1932 Param *bool 1933 } 1934 ` 1935 1936 boolContextFactory = ` 1937 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1938 var err error 1939 resp := goa.ContextResponse(ctx) 1940 resp.Service = service 1941 req := goa.ContextRequest(ctx) 1942 req.Request = r 1943 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1944 paramParam := req.Params["param"] 1945 if len(paramParam) > 0 { 1946 rawParam := paramParam[0] 1947 if param, err2 := strconv.ParseBool(rawParam); err2 == nil { 1948 tmp1 := ¶m 1949 rctx.Param = tmp1 1950 } else { 1951 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "boolean")) 1952 } 1953 } 1954 return &rctx, err 1955 } 1956 ` 1957 1958 boolNonOptionalContext = ` 1959 type ListBottleContext struct { 1960 context.Context 1961 *goa.ResponseData 1962 *goa.RequestData 1963 Param bool 1964 } 1965 ` 1966 1967 boolDefaultContextFactory = ` 1968 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1969 var err error 1970 resp := goa.ContextResponse(ctx) 1971 resp.Service = service 1972 req := goa.ContextRequest(ctx) 1973 req.Request = r 1974 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1975 paramParam := req.Params["param"] 1976 if len(paramParam) == 0 { 1977 rctx.Param = true 1978 } else { 1979 rawParam := paramParam[0] 1980 if param, err2 := strconv.ParseBool(rawParam); err2 == nil { 1981 rctx.Param = param 1982 } else { 1983 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "boolean")) 1984 } 1985 } 1986 return &rctx, err 1987 } 1988 ` 1989 1990 boolRequiredContextFactory = ` 1991 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 1992 var err error 1993 resp := goa.ContextResponse(ctx) 1994 resp.Service = service 1995 req := goa.ContextRequest(ctx) 1996 req.Request = r 1997 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 1998 paramParam := req.Params["param"] 1999 if len(paramParam) == 0 { 2000 err = goa.MergeErrors(err, goa.MissingParamError("param")) 2001 } else { 2002 rawParam := paramParam[0] 2003 if param, err2 := strconv.ParseBool(rawParam); err2 == nil { 2004 rctx.Param = param 2005 } else { 2006 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "boolean")) 2007 } 2008 } 2009 return &rctx, err 2010 } 2011 ` 2012 2013 arrayContext = ` 2014 type ListBottleContext struct { 2015 context.Context 2016 *goa.ResponseData 2017 *goa.RequestData 2018 Param []string 2019 } 2020 ` 2021 2022 arrayContextFactory = ` 2023 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2024 var err error 2025 resp := goa.ContextResponse(ctx) 2026 resp.Service = service 2027 req := goa.ContextRequest(ctx) 2028 req.Request = r 2029 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2030 paramParam := req.Params["param"] 2031 if len(paramParam) > 0 { 2032 params := paramParam 2033 rctx.Param = params 2034 } 2035 return &rctx, err 2036 } 2037 ` 2038 2039 arrayParamContextFactory = ` 2040 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2041 var err error 2042 resp := goa.ContextResponse(ctx) 2043 resp.Service = service 2044 req := goa.ContextRequest(ctx) 2045 req.Request = r 2046 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2047 paramParam := req.Params["param"] 2048 if len(paramParam) > 0 { 2049 params := paramParam 2050 rctx.Param = params 2051 } 2052 return &rctx, err 2053 } 2054 ` 2055 2056 arrayDefaultContextFactory = ` 2057 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2058 var err error 2059 resp := goa.ContextResponse(ctx) 2060 resp.Service = service 2061 req := goa.ContextRequest(ctx) 2062 req.Request = r 2063 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2064 paramParam := req.Params["param"] 2065 if len(paramParam) == 0 { 2066 rctx.Param = []string{"foo", "bar", "baz"} 2067 } else { 2068 params := paramParam 2069 rctx.Param = params 2070 } 2071 return &rctx, err 2072 } 2073 ` 2074 2075 arrayRequiredContextFactory = ` 2076 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2077 var err error 2078 resp := goa.ContextResponse(ctx) 2079 resp.Service = service 2080 req := goa.ContextRequest(ctx) 2081 req.Request = r 2082 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2083 paramParam := req.Params["param"] 2084 if len(paramParam) == 0 { 2085 err = goa.MergeErrors(err, goa.MissingParamError("param")) 2086 } else { 2087 params := paramParam 2088 rctx.Param = params 2089 } 2090 return &rctx, err 2091 } 2092 ` 2093 2094 intArrayContext = ` 2095 type ListBottleContext struct { 2096 context.Context 2097 *goa.ResponseData 2098 *goa.RequestData 2099 Param []int 2100 } 2101 ` 2102 2103 intArrayContextFactory = ` 2104 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2105 var err error 2106 resp := goa.ContextResponse(ctx) 2107 resp.Service = service 2108 req := goa.ContextRequest(ctx) 2109 req.Request = r 2110 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2111 paramParam := req.Params["param"] 2112 if len(paramParam) > 0 { 2113 params := make([]int, len(paramParam)) 2114 for i, rawParam := range paramParam { 2115 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 2116 params[i] = param 2117 } else { 2118 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 2119 } 2120 } 2121 rctx.Param = params 2122 } 2123 return &rctx, err 2124 } 2125 ` 2126 2127 intArrayDefaultContextFactory = ` 2128 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2129 var err error 2130 resp := goa.ContextResponse(ctx) 2131 resp.Service = service 2132 req := goa.ContextRequest(ctx) 2133 req.Request = r 2134 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2135 paramParam := req.Params["param"] 2136 if len(paramParam) == 0 { 2137 rctx.Param = []int{1, 1, 2, 3, 5, 8} 2138 } else { 2139 params := make([]int, len(paramParam)) 2140 for i, rawParam := range paramParam { 2141 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 2142 params[i] = param 2143 } else { 2144 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 2145 } 2146 } 2147 rctx.Param = params 2148 } 2149 return &rctx, err 2150 } 2151 ` 2152 2153 intArrayRequiredContextFactory = ` 2154 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2155 var err error 2156 resp := goa.ContextResponse(ctx) 2157 resp.Service = service 2158 req := goa.ContextRequest(ctx) 2159 req.Request = r 2160 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2161 paramParam := req.Params["param"] 2162 if len(paramParam) == 0 { 2163 err = goa.MergeErrors(err, goa.MissingParamError("param")) 2164 } else { 2165 params := make([]int, len(paramParam)) 2166 for i, rawParam := range paramParam { 2167 if param, err2 := strconv.Atoi(rawParam); err2 == nil { 2168 params[i] = param 2169 } else { 2170 err = goa.MergeErrors(err, goa.InvalidParamTypeError("param", rawParam, "integer")) 2171 } 2172 } 2173 rctx.Param = params 2174 } 2175 return &rctx, err 2176 } 2177 ` 2178 2179 resContext = ` 2180 type ListBottleContext struct { 2181 context.Context 2182 *goa.ResponseData 2183 *goa.RequestData 2184 Int *int 2185 } 2186 ` 2187 2188 resContextFactory = ` 2189 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2190 var err error 2191 resp := goa.ContextResponse(ctx) 2192 resp.Service = service 2193 req := goa.ContextRequest(ctx) 2194 req.Request = r 2195 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2196 paramInt := req.Params["int"] 2197 if len(paramInt) > 0 { 2198 rawInt := paramInt[0] 2199 if int_, err2 := strconv.Atoi(rawInt); err2 == nil { 2200 tmp2 := int_ 2201 tmp1 := &tmp2 2202 rctx.Int = tmp1 2203 } else { 2204 err = goa.MergeErrors(err, goa.InvalidParamTypeError("int", rawInt, "integer")) 2205 } 2206 } 2207 return &rctx, err 2208 } 2209 ` 2210 2211 requiredContext = ` 2212 type ListBottleContext struct { 2213 context.Context 2214 *goa.ResponseData 2215 *goa.RequestData 2216 Int int 2217 } 2218 ` 2219 2220 requiredContextFactory = ` 2221 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2222 var err error 2223 resp := goa.ContextResponse(ctx) 2224 resp.Service = service 2225 req := goa.ContextRequest(ctx) 2226 req.Request = r 2227 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2228 paramInt := req.Params["int"] 2229 if len(paramInt) == 0 { 2230 err = goa.MergeErrors(err, goa.MissingParamError("int")) 2231 } else { 2232 rawInt := paramInt[0] 2233 if int_, err2 := strconv.Atoi(rawInt); err2 == nil { 2234 rctx.Int = int_ 2235 } else { 2236 err = goa.MergeErrors(err, goa.InvalidParamTypeError("int", rawInt, "integer")) 2237 } 2238 } 2239 return &rctx, err 2240 } 2241 ` 2242 2243 customContext = ` 2244 type ListBottleContext struct { 2245 context.Context 2246 *goa.ResponseData 2247 *goa.RequestData 2248 Custom *int 2249 } 2250 ` 2251 2252 customContextFactory = ` 2253 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2254 var err error 2255 resp := goa.ContextResponse(ctx) 2256 resp.Service = service 2257 req := goa.ContextRequest(ctx) 2258 req.Request = r 2259 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2260 paramInt := req.Params["int"] 2261 if len(paramInt) > 0 { 2262 rawInt := paramInt[0] 2263 if int_, err2 := strconv.Atoi(rawInt); err2 == nil { 2264 tmp2 := int_ 2265 tmp1 := &tmp2 2266 rctx.Custom = tmp1 2267 } else { 2268 err = goa.MergeErrors(err, goa.InvalidParamTypeError("int", rawInt, "integer")) 2269 } 2270 } 2271 return &rctx, err 2272 } 2273 ` 2274 2275 payloadContext = ` 2276 type ListBottleContext struct { 2277 context.Context 2278 *goa.ResponseData 2279 *goa.RequestData 2280 Payload ListBottlePayload 2281 } 2282 ` 2283 2284 payloadContextFactory = ` 2285 func NewListBottleContext(ctx context.Context, r *http.Request, service *goa.Service) (*ListBottleContext, error) { 2286 var err error 2287 resp := goa.ContextResponse(ctx) 2288 resp.Service = service 2289 req := goa.ContextRequest(ctx) 2290 req.Request = r 2291 rctx := ListBottleContext{Context: ctx, ResponseData: resp, RequestData: req} 2292 return &rctx, err 2293 } 2294 ` 2295 payloadObjContext = ` 2296 type ListBottleContext struct { 2297 context.Context 2298 *goa.ResponseData 2299 *goa.RequestData 2300 Payload *ListBottlePayload 2301 } 2302 ` 2303 2304 payloadObjUnmarshal = ` 2305 func unmarshalListBottlePayload(ctx context.Context, service *goa.Service, req *http.Request) error { 2306 payload := &listBottlePayload{} 2307 if err := service.DecodeRequest(req, payload); err != nil { 2308 return err 2309 } 2310 if err := payload.Validate(); err != nil { 2311 // Initialize payload with private data structure so it can be logged 2312 goa.ContextRequest(ctx).Payload = payload 2313 return err 2314 } 2315 goa.ContextRequest(ctx).Payload = payload.Publicize() 2316 return nil 2317 } 2318 ` 2319 2320 payloadMultipartObjUnmarshal = ` 2321 func unmarshalListBottlePayload(ctx context.Context, service *goa.Service, req *http.Request) error { 2322 var err error 2323 var payload listBottlePayload 2324 _, rawIcon, err2 := req.FormFile("icon") 2325 if err2 == nil { 2326 payload.Icon = rawIcon 2327 } else { 2328 err = goa.MergeErrors(err, goa.InvalidParamTypeError("icon", "icon", "file")) 2329 } 2330 rawID := req.FormValue("id") 2331 payload.ID = &rawID 2332 if err != nil { 2333 return err 2334 } 2335 if err := payload.Validate(); err != nil { 2336 // Initialize payload with private data structure so it can be logged 2337 goa.ContextRequest(ctx).Payload = payload 2338 return err 2339 } 2340 goa.ContextRequest(ctx).Payload = payload.Publicize() 2341 return nil 2342 } 2343 ` 2344 2345 payloadNoValidationsObjUnmarshal = ` 2346 func unmarshalListBottlePayload(ctx context.Context, service *goa.Service, req *http.Request) error { 2347 payload := &listBottlePayload{} 2348 if err := service.DecodeRequest(req, payload); err != nil { 2349 return err 2350 } 2351 goa.ContextRequest(ctx).Payload = payload.Publicize() 2352 return nil 2353 } 2354 ` 2355 2356 simpleFileServer = `// PublicController is the controller interface for the Public actions. 2357 type PublicController interface { 2358 goa.Muxer 2359 goa.FileServer 2360 } 2361 ` 2362 2363 fileServerOptionsHandler = `service.Mux.Handle("OPTIONS", "/public/star\\*star/*filepath", ctrl.MuxHandler("preflight", handlePublicOrigin(cors.HandlePreflight()), nil))` 2364 2365 simpleController = `// BottlesController is the controller interface for the Bottles actions. 2366 type BottlesController interface { 2367 goa.Muxer 2368 List(*ListBottleContext) error 2369 } 2370 ` 2371 2372 originsIntegration = `} 2373 h = handleBottlesOrigin(h) 2374 service.Mux.Handle` 2375 2376 originsHandler = `// handleBottlesOrigin applies the CORS response headers corresponding to the origin. 2377 func handleBottlesOrigin(h goa.Handler) goa.Handler { 2378 2379 return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2380 origin := req.Header.Get("Origin") 2381 if origin == "" { 2382 // Not a CORS request 2383 return h(ctx, rw, req) 2384 } 2385 if cors.MatchOrigin(origin, "here.example.com") { 2386 ctx = goa.WithLogContext(ctx, "origin", origin) 2387 rw.Header().Set("Access-Control-Allow-Origin", origin) 2388 rw.Header().Set("Vary", "Origin") 2389 rw.Header().Set("Access-Control-Expose-Headers", "X-Three") 2390 rw.Header().Set("Access-Control-Allow-Credentials", "true") 2391 if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" { 2392 // We are handling a preflight request 2393 rw.Header().Set("Access-Control-Allow-Methods", "GET, POST") 2394 rw.Header().Set("Access-Control-Allow-Headers", "X-One, X-Two") 2395 } 2396 return h(ctx, rw, req) 2397 } 2398 if cors.MatchOrigin(origin, "there.example.com") { 2399 ctx = goa.WithLogContext(ctx, "origin", origin) 2400 rw.Header().Set("Access-Control-Allow-Origin", origin) 2401 rw.Header().Set("Vary", "Origin") 2402 rw.Header().Set("Access-Control-Allow-Credentials", "false") 2403 if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" { 2404 // We are handling a preflight request 2405 rw.Header().Set("Access-Control-Allow-Methods", "*") 2406 rw.Header().Set("Access-Control-Allow-Headers", "*") 2407 } 2408 return h(ctx, rw, req) 2409 } 2410 2411 return h(ctx, rw, req) 2412 } 2413 } 2414 ` 2415 2416 regexpOriginsHandler = `// handleBottlesOrigin applies the CORS response headers corresponding to the origin. 2417 func handleBottlesOrigin(h goa.Handler) goa.Handler { 2418 spec0 := regexp.MustCompile("[here|there].example.com") 2419 2420 return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2421 origin := req.Header.Get("Origin") 2422 if origin == "" { 2423 // Not a CORS request 2424 return h(ctx, rw, req) 2425 } 2426 if cors.MatchOriginRegexp(origin, spec0) { 2427 ctx = goa.WithLogContext(ctx, "origin", origin) 2428 rw.Header().Set("Access-Control-Allow-Origin", origin) 2429 rw.Header().Set("Vary", "Origin") 2430 rw.Header().Set("Access-Control-Expose-Headers", "X-Three") 2431 rw.Header().Set("Access-Control-Allow-Credentials", "true") 2432 if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" { 2433 // We are handling a preflight request 2434 rw.Header().Set("Access-Control-Allow-Methods", "GET, POST") 2435 rw.Header().Set("Access-Control-Allow-Headers", "X-One, X-Two") 2436 } 2437 return h(ctx, rw, req) 2438 } 2439 if cors.MatchOrigin(origin, "there.example.com") { 2440 ctx = goa.WithLogContext(ctx, "origin", origin) 2441 rw.Header().Set("Access-Control-Allow-Origin", origin) 2442 rw.Header().Set("Vary", "Origin") 2443 rw.Header().Set("Access-Control-Allow-Credentials", "false") 2444 if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" { 2445 // We are handling a preflight request 2446 rw.Header().Set("Access-Control-Allow-Methods", "*") 2447 rw.Header().Set("Access-Control-Allow-Headers", "*") 2448 } 2449 return h(ctx, rw, req) 2450 } 2451 2452 return h(ctx, rw, req) 2453 } 2454 } 2455 ` 2456 2457 encoderController = ` 2458 // MountBottlesController "mounts" a Bottles resource controller on the given service. 2459 func MountBottlesController(service *goa.Service, ctrl BottlesController) { 2460 initService(service) 2461 var h goa.Handler 2462 2463 h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2464 // Check if there was an error loading the request 2465 if err := goa.ContextError(ctx); err != nil { 2466 return err 2467 } 2468 // Build the context 2469 rctx, err := NewListBottleContext(ctx, req, service) 2470 if err != nil { 2471 return err 2472 } 2473 return ctrl.List(rctx) 2474 } 2475 service.Mux.Handle("GET", "/accounts/:accountID/bottles", ctrl.MuxHandler("list", h, nil)) 2476 service.LogInfo("mount", "ctrl", "Bottles", "action", "List", "route", "GET /accounts/:accountID/bottles") 2477 } 2478 ` 2479 2480 simpleMount = `func MountBottlesController(service *goa.Service, ctrl BottlesController) { 2481 initService(service) 2482 var h goa.Handler 2483 2484 h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2485 // Check if there was an error loading the request 2486 if err := goa.ContextError(ctx); err != nil { 2487 return err 2488 } 2489 // Build the context 2490 rctx, err := NewListBottleContext(ctx, req, service) 2491 if err != nil { 2492 return err 2493 } 2494 return ctrl.List(rctx) 2495 } 2496 service.Mux.Handle("GET", "/accounts/:accountID/bottles", ctrl.MuxHandler("list", h, nil)) 2497 service.LogInfo("mount", "ctrl", "Bottles", "action", "List", "route", "GET /accounts/:accountID/bottles") 2498 } 2499 ` 2500 2501 multiController = `// BottlesController is the controller interface for the Bottles actions. 2502 type BottlesController interface { 2503 goa.Muxer 2504 List(*ListBottleContext) error 2505 Show(*ShowBottleContext) error 2506 } 2507 ` 2508 2509 multiMount = `func MountBottlesController(service *goa.Service, ctrl BottlesController) { 2510 initService(service) 2511 var h goa.Handler 2512 2513 h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2514 // Check if there was an error loading the request 2515 if err := goa.ContextError(ctx); err != nil { 2516 return err 2517 } 2518 // Build the context 2519 rctx, err := NewListBottleContext(ctx, req, service) 2520 if err != nil { 2521 return err 2522 } 2523 return ctrl.List(rctx) 2524 } 2525 service.Mux.Handle("GET", "/accounts/:accountID/bottles", ctrl.MuxHandler("list", h, nil)) 2526 service.LogInfo("mount", "ctrl", "Bottles", "action", "List", "route", "GET /accounts/:accountID/bottles") 2527 2528 h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error { 2529 // Check if there was an error loading the request 2530 if err := goa.ContextError(ctx); err != nil { 2531 return err 2532 } 2533 // Build the context 2534 rctx, err := NewShowBottleContext(ctx, req, service) 2535 if err != nil { 2536 return err 2537 } 2538 return ctrl.Show(rctx) 2539 } 2540 service.Mux.Handle("GET", "/accounts/:accountID/bottles/:id", ctrl.MuxHandler("show", h, nil)) 2541 service.LogInfo("mount", "ctrl", "Bottles", "action", "Show", "route", "GET /accounts/:accountID/bottles/:id") 2542 } 2543 ` 2544 2545 simpleResourceHref = `func BottleHref(id interface{}) string { 2546 paramid := strings.TrimLeftFunc(fmt.Sprintf("%v", id), func(r rune) bool { return r == '/' }) 2547 return fmt.Sprintf("/bottles/%v", paramid) 2548 } 2549 ` 2550 noParamHref = `func BottleHref() string { 2551 return "/bottles" 2552 } 2553 ` 2554 2555 simpleUserType = `// simplePayload user type. 2556 type simplePayload struct { 2557 Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty" xml:"name,omitempty"` + "`" + ` 2558 } 2559 2560 2561 2562 // Publicize creates SimplePayload from simplePayload 2563 func (ut *simplePayload) Publicize() *SimplePayload { 2564 var pub SimplePayload 2565 if ut.Name != nil { 2566 pub.Name = ut.Name 2567 } 2568 return &pub 2569 } 2570 2571 // SimplePayload user type. 2572 type SimplePayload struct { 2573 Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty" xml:"name,omitempty"` + "`" + ` 2574 } 2575 ` 2576 2577 userTypeIncludingHash = `// complexPayload user type. 2578 type complexPayload struct { 2579 Misc map[int]*miscPayload ` + "`" + `form:"misc,omitempty" json:"misc,omitempty" yaml:"misc,omitempty" xml:"misc,omitempty"` + "`" + ` 2580 Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty" xml:"name,omitempty"` + "`" + ` 2581 } 2582 2583 2584 2585 // Publicize creates ComplexPayload from complexPayload 2586 func (ut *complexPayload) Publicize() *ComplexPayload { 2587 var pub ComplexPayload 2588 if ut.Misc != nil { 2589 pub.Misc = make(map[int]*MiscPayload, len(ut.Misc)) 2590 for k2, v2 := range ut.Misc { 2591 pubk2 := k2 2592 var pubv2 *MiscPayload 2593 if v2 != nil { 2594 pubv2 = v2.Publicize() 2595 } 2596 pub.Misc[pubk2] = pubv2 2597 } 2598 } 2599 if ut.Name != nil { 2600 pub.Name = ut.Name 2601 } 2602 return &pub 2603 } 2604 2605 // ComplexPayload user type. 2606 type ComplexPayload struct { 2607 Misc map[int]*MiscPayload ` + "`" + `form:"misc,omitempty" json:"misc,omitempty" yaml:"misc,omitempty" xml:"misc,omitempty"` + "`" + ` 2608 Name *string ` + "`" + `form:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty" xml:"name,omitempty"` + "`" + ` 2609 } 2610 ` 2611 )