github.com/brycereitano/goa@v0.0.0-20170315073847-8ffa6c85e265/goagen/gen_app/test_generator_test.go (about)

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