diff --git a/magefiles/magefile.go b/magefiles/magefile.go index 481c36c0f7..53e2acebe8 100644 --- a/magefiles/magefile.go +++ b/magefiles/magefile.go @@ -758,26 +758,31 @@ func GenerateTextOutlineFromGinkgoSpec(source string, destination string) error } // Generate a Ginkgo Spec file from a Text Outline file -func GenerateGinkoSpecFromTextOutline(source string, destination string) error { +func GenerateGinkgoSpecFromTextOutline(source string, destination string) error { + return GenerateTeamSpecificGinkgoSpecFromTextOutline(source, testspecs.TestFilePath, destination) +} +// Generate a team specific file using specs in templates/specs.tmpl file and a provided team specific template +func GenerateTeamSpecificGinkgoSpecFromTextOutline(outlinePath, teamTmplPath, destinationPath string) error { gs := testspecs.NewGinkgoSpecTranslator() ts := testspecs.NewTextSpecTranslator() - klog.Infof("Mapping outline from a text file, %s", source) - outline, err := ts.FromFile(source) + klog.Infof("Mapping outline from a text file, %s", outlinePath) + outline, err := ts.FromFile(outlinePath) if err != nil { klog.Error("Failed to map text outline file") return err } - klog.Infof("Mapping outline to a Ginkgo spec file, %s", destination) - err = gs.ToFile(destination, outline) + klog.Infof("Mapping outline to a Ginkgo spec file, %s", destinationPath) + err = gs.ToFile(destinationPath, teamTmplPath, outline) if err != nil { klog.Error("Failed to map Ginkgo spec file") return err } return err + } // Print the outline of the Ginkgo spec diff --git a/magefiles/testspecs/ginkgosspec.go b/magefiles/testspecs/ginkgosspec.go index 0bf9240a48..33f61f4645 100644 --- a/magefiles/testspecs/ginkgosspec.go +++ b/magefiles/testspecs/ginkgosspec.go @@ -3,7 +3,7 @@ package testspecs import ( "encoding/json" "fmt" - + "io" "os" "path/filepath" "reflect" @@ -54,7 +54,7 @@ func (gst *GinkgosSpecTranslator) FromFile(file string) (TestOutline, error) { } // ToFile generates a Ginkgo test file from a TestOutline -func (gst *GinkgosSpecTranslator) ToFile(destination string, outline TestOutline) error { +func (gst *GinkgosSpecTranslator) ToFile(destination, teamTmplPath string, outline TestOutline) error { e2ePath, err := os.Getwd() if err != nil { @@ -71,7 +71,7 @@ func (gst *GinkgosSpecTranslator) ToFile(destination string, outline TestOutline return err } - return generateGinkgoSpec(e2ePath, testFilePath, dataFile) + return generateGinkgoSpec(e2ePath, teamTmplPath, testFilePath, dataFile) } @@ -112,10 +112,19 @@ func excludeSetupTeardownNodes(nodes TestOutline) TestOutline { // generateGinkgoSpec will call the ginkgo generate command // to generate the ginkgo data json file we created and // the template located in out templates directory -func generateGinkgoSpec(cwd string, destination string, dataFile string) error { +func generateGinkgoSpec(cwd, teamTmplPath, destination string, dataFile string) error { var err error + if teamTmplPath != TestFilePath { + tmplFile, err := mergeTemplates(teamTmplPath, SpecsPath) + if err != nil { + return err + } + defer os.Remove(tmplFile.Name()) + teamTmplPath = tmplFile.Name() + } + // Note I change into the directory and rename things because ginkgo // by default generates the test file name as _test.go. // Since that is not a semantic we follow I perform this action. @@ -136,7 +145,7 @@ func generateGinkgoSpec(cwd string, destination string, dataFile string) error { // issues 101, 77, 55 klog.Infof("Creating new test package directory and spec file %s.\n", destination) - _, err = ginkgoGenerateSpecCmd("--template", TestFilePath, "--template-data", dataFile) + _, err = ginkgoGenerateSpecCmd("--template", teamTmplPath, "--template-data", dataFile) if err != nil { err = os.Remove(ginkgoFileName) if err != nil { @@ -164,6 +173,39 @@ func generateGinkgoSpec(cwd string, destination string, dataFile string) error { return err } +// mergeTemplates creates a new template file from files provided in the argument +func mergeTemplates(paths ...string) (*os.File, error) { + cwd, err := os.Getwd() + if err != nil { + return nil, err + } + + tempFile, err := os.CreateTemp(cwd, "merged-tmpl") + if err != nil { + return nil, err + } + defer tempFile.Close() + + for _, path := range paths { + tmplFile, err := os.Open(cwd + "/" + path) + if err != nil { + return nil, err + } + defer tmplFile.Close() + + _, err = io.Copy(tempFile, tmplFile) + if err != nil { + return nil, err + } + + _, err = tempFile.Write([]byte{'\n', '\n'}) + if err != nil { + return nil, err + } + } + return tempFile, nil +} + // createTestPath will create the full test path in the tests // directory if it doesn't exit func createTestPath(cwd string, destination string) (string, error) { diff --git a/templates/specs.tmpl b/templates/specs.tmpl new file mode 100644 index 0000000000..acb02b4a43 --- /dev/null +++ b/templates/specs.tmpl @@ -0,0 +1,121 @@ +{{ define "specs" }} + {{ range .Nodes }} + {{ if eq .Name "DescribeTable" }} + {{ .Name }}("{{ .Text }} is table", + func() { + {{range .Nodes }} + {{ if eq .Name "By" }} + {{ .Name }}("{{ .Text }}") + {{ end -}} + {{ end -}} + }, + {{range .Nodes }} + {{ if eq .Name "Entry" }} + {{ .Name }}("{{ .Text }}",), + {{ end -}} + {{ end -}} + ) + {{ end -}} + {{ if ne .Name "DescribeTable" }} + {{ .Name }}("{{ .Text }}", {{range .Labels }}Label("{{.}}"), {{ end }}func() { + // Declare variables here. + {{range .Nodes }} + {{ if eq .Name "DescribeTable" }} + {{ .Name }}("{{ .Text }}", + func() { + {{range .Nodes }} + {{ if eq .Name "By" }} + {{ .Name }}("{{ .Text }}") + {{ end -}} + {{ end -}} + }, + {{range .Nodes }} + {{ if eq .Name "Entry" }} + {{ .Name }}("{{ .Text }}",), + {{ end -}} + {{ end -}} + ) + {{ end -}} + {{ if eq .Name "By" }} + {{ .Name }}("{{ .Text }}") + {{ continue }} + {{ end -}} + {{ if eq .Name "Entry" }} + {{ continue }} + {{ end -}} + {{ if ne .Name "DescribeTable" -}} + {{ .Name }}("{{ .Text }}", {{range .Labels }}Label("{{.}}"), {{ end }} func() { + {{ if eq .Name "It" -}} + // Implement test and assertions here + {{ end -}} + {{ range .Nodes -}} + {{ if eq .Name "DescribeTable" -}} + {{ .Name }}("{{ .Text }}", + func() { + {{range .Nodes -}} + {{ if eq .Name "By" -}} + {{ .Name }}("{{ .Text }}") + {{ end -}} + {{ end -}} + }, + {{range .Nodes -}} + {{ if eq .Name "Entry" -}} + {{ .Name }}("{{ .Text }}",), + {{ end -}} + {{ end -}} + ) + {{ end }} + {{ if eq .Name "By" -}} + {{ .Name }}("{{ .Text }}") + {{ continue }} + {{ end -}} + {{ if eq .Name "Entry" -}} + {{ continue }} + {{ end -}} + {{ if ne .Name "DescribeTable" -}} + {{ .Name }}("{{ .Text }}", {{range .Labels }}Label("{{.}}"), {{ end }} func() { + {{ if eq .Name "It" -}} + // Implement test and assertions here + {{ end -}} + {{ range .Nodes -}} + {{ if eq .Name "DescribeTable" -}} + {{ .Name }}("{{ .Text }}", + func() { + {{range .Nodes }} + {{ if eq .Name "By" }} + {{ .Name }}("{{ .Text }}") + {{ end -}} + {{ end -}} + }, + {{range .Nodes }} + {{ if eq .Name "Entry" }} + {{ .Name }}("{{ .Text }}",), + {{ end -}} + {{ end -}} + ) + {{ end -}} + {{ if eq .Name "By" }} + {{ .Name }}("{{ .Text }}") + {{ continue }} + {{ end -}} + {{ if eq .Name "Entry" }} + {{ continue }} + {{ end -}} + {{ if ne .Name "DescribeTable" }} + {{ .Name }}("{{ .Text }}", {{range .Labels }}Label("{{.}}"), {{ end }} func() { + {{ if eq .Name "It" -}} + // Implement test and assertions here + {{ end }} + }) + {{ end -}} + {{ end }} + }) + {{ end -}} + {{ end }} + }) + {{ end -}} + {{ end }} + }) + {{ end -}} + {{ end -}} +{{ end }} \ No newline at end of file