github.com/furusax0621/goa-v1@v1.4.3/goagen/gen_app/test_generator_test.go (about)

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