github.com/vugu/vugu@v0.3.5/gen/parser-go-pkg_test.go (about)

     1  package gen
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"os"
     7  	"os/exec"
     8  	"path/filepath"
     9  	"regexp"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func TestSimpleParseGoPkgRun(t *testing.T) {
    16  
    17  	assert := assert.New(t)
    18  
    19  	tmpDir, err := ioutil.TempDir("", "TestParseGoPkgRun")
    20  	if err != nil {
    21  		t.Fatal(err)
    22  	}
    23  	defer os.RemoveAll(tmpDir)
    24  
    25  	// 	assert.NoError(ioutil.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte(`
    26  	// module main
    27  	// `), 0644))
    28  
    29  	assert.NoError(ioutil.WriteFile(filepath.Join(tmpDir, "root.vugu"), []byte(`
    30  <div id="root_comp">
    31  	<h1>Hello!</h1>
    32  </div>
    33  `), 0644))
    34  
    35  	p := NewParserGoPkg(tmpDir, nil)
    36  
    37  	assert.NoError(p.Run())
    38  
    39  	b, err := ioutil.ReadFile(filepath.Join(tmpDir, "root_vgen.go"))
    40  	assert.NoError(err)
    41  	// t.Logf("OUT FILE root_vgen.go: %s", b)
    42  	// log.Printf("OUT FILE root_vgen.go: %s", b)
    43  
    44  	if !bytes.Contains(b, []byte(`func (c *Root) Build`)) {
    45  		t.Errorf("failed to find Build method signature")
    46  	}
    47  
    48  	b, err = ioutil.ReadFile(filepath.Join(tmpDir, "0_missing_vgen.go"))
    49  	assert.NoError(err)
    50  
    51  	if !bytes.Contains(b, []byte(`type Root struct`)) {
    52  		t.Errorf("failed to find Root struct definition")
    53  	}
    54  
    55  }
    56  
    57  func TestRun(t *testing.T) {
    58  
    59  	debug := false
    60  
    61  	pwd, err := filepath.Abs("..")
    62  	if err != nil {
    63  		t.Fatal(err)
    64  	}
    65  
    66  	type tcase struct {
    67  		name      string
    68  		opts      ParserGoPkgOpts
    69  		recursive bool
    70  		infiles   map[string]string              // file structure to start with
    71  		out       map[string][]string            // regexps to match in output files
    72  		afterRun  func(dir string, t *testing.T) // called after Run
    73  		bfiles    map[string]string              // additional files to write before building
    74  		build     string                         // "wasm", "default", "none"
    75  	}
    76  
    77  	tcList := []tcase{
    78  		{
    79  			name:      "simple",
    80  			opts:      ParserGoPkgOpts{},
    81  			recursive: false,
    82  			infiles: map[string]string{
    83  				"root.vugu": `<div>root here</div>`,
    84  				"go.mod":    "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n",
    85  				"main.go":   "package main\nfunc main(){}",
    86  			},
    87  			out: map[string][]string{
    88  				"root_vgen.go":      {`func \(c \*Root\) Build`},
    89  				"0_missing_vgen.go": {`type Root struct`},
    90  			},
    91  			build: "default",
    92  		},
    93  		{
    94  			name:      "simple-wasm",
    95  			opts:      ParserGoPkgOpts{},
    96  			recursive: false,
    97  			infiles: map[string]string{
    98  				"root.vugu": `<div>root here</div>`,
    99  				"go.mod":    "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n",
   100  			},
   101  			out: map[string][]string{
   102  				"root_vgen.go":      {`func \(c \*Root\) Build`},
   103  				"0_missing_vgen.go": {`type Root struct`},
   104  			},
   105  			build: "wasm",
   106  		},
   107  		{
   108  			name:      "recursive",
   109  			opts:      ParserGoPkgOpts{},
   110  			recursive: true,
   111  			infiles: map[string]string{
   112  				"root.vugu":            `<div>root here</div>`,
   113  				"go.mod":               "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n",
   114  				"main.go":              "package main\nfunc main(){}",
   115  				"subdir1/example.vugu": "<div>Example Here</div>",
   116  			},
   117  			out: map[string][]string{
   118  				"root_vgen.go":            {`func \(c \*Root\) Build`, `root here`},
   119  				"0_missing_vgen.go":       {`type Root struct`},
   120  				"subdir1/example_vgen.go": {`Example Here`},
   121  			},
   122  			build: "default",
   123  		},
   124  		{
   125  			name:      "recursive-single",
   126  			opts:      ParserGoPkgOpts{MergeSingle: true},
   127  			recursive: true,
   128  			infiles: map[string]string{
   129  				"root.vugu":            `<div>root here</div>`,
   130  				"go.mod":               "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n",
   131  				"main.go":              "package main\nfunc main(){}",
   132  				"subdir1/example.vugu": "<div>Example Here</div>",
   133  			},
   134  			out: map[string][]string{
   135  				"0_components_vgen.go":         {`func \(c \*Root\) Build`, `type Root struct`},
   136  				"subdir1/0_components_vgen.go": {`Example Here`},
   137  				"root.vugu":                    {`root here`}, // make sure vugu files didn't get nuked
   138  				"subdir1/example.vugu":         {`Example Here`},
   139  			},
   140  			afterRun: func(dir string, t *testing.T) {
   141  				noFile(filepath.Join(dir, "subdir1/example_vgen.go"), t)
   142  			},
   143  			build: "default",
   144  		},
   145  		{
   146  			name:      "events",
   147  			opts:      ParserGoPkgOpts{},
   148  			recursive: false,
   149  			infiles: map[string]string{
   150  				"root.vugu": `<div>root here</div>`,
   151  				"go.mod":    "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n",
   152  				"main.go":   "package main\nfunc main(){}\n\n//vugugen:event Sample\n",
   153  			},
   154  			out: map[string][]string{
   155  				"root_vgen.go":      {`func \(c \*Root\) Build`},
   156  				"0_missing_vgen.go": {`type Root struct`, `SampleEvent`, `SampleHandler`, `SampleFunc`},
   157  			},
   158  			build: "default",
   159  		},
   160  	}
   161  
   162  	for _, tc := range tcList {
   163  		tc := tc
   164  		t.Run(tc.name, func(t *testing.T) {
   165  
   166  			tmpDir, err := ioutil.TempDir("", "TestRun")
   167  			if err != nil {
   168  				t.Fatal(err)
   169  			}
   170  
   171  			if debug {
   172  				t.Logf("Test %q using tmpDir: %s", tc.name, tmpDir)
   173  			} else {
   174  				t.Parallel()
   175  			}
   176  
   177  			tstWriteFiles(tmpDir, tc.infiles)
   178  
   179  			if tc.recursive {
   180  				err = RunRecursive(tmpDir, &tc.opts)
   181  			} else {
   182  				err = Run(tmpDir, &tc.opts)
   183  			}
   184  			if err != nil {
   185  				t.Fatal(err)
   186  			}
   187  
   188  			for fname, patterns := range tc.out {
   189  				b, err := ioutil.ReadFile(filepath.Join(tmpDir, fname))
   190  				if err != nil {
   191  					t.Errorf("failed to read file %q after Run: %v", fname, err)
   192  					continue
   193  				}
   194  				for _, pattern := range patterns {
   195  					re := regexp.MustCompile(pattern)
   196  					if !re.Match(b) {
   197  						t.Errorf("failed to match regexp on file %q: %s", fname, pattern)
   198  					}
   199  				}
   200  			}
   201  
   202  			if tc.afterRun != nil {
   203  				tc.afterRun(tmpDir, t)
   204  			}
   205  
   206  			tstWriteFiles(tmpDir, tc.bfiles)
   207  
   208  			cmd := exec.Command("go", "mod", "tidy")
   209  			cmd.Dir = tmpDir
   210  			b, err := cmd.CombinedOutput()
   211  			if err != nil {
   212  				t.Fatalf("go mod tidy error: %s; OUTPUT:\n%s", err, b)
   213  			}
   214  
   215  			switch tc.build {
   216  
   217  			case "wasm":
   218  				cmd := exec.Command("go", "build", "-o", "main.wasm", ".")
   219  				cmd.Dir = tmpDir
   220  				cmd.Env = os.Environ() // needed?
   221  				cmd.Env = append(cmd.Env, "GOOS=js", "GOARCH=wasm")
   222  				b, err := cmd.CombinedOutput()
   223  				if err != nil {
   224  					t.Fatalf("build error: %s; OUTPUT:\n%s", err, b)
   225  				}
   226  
   227  			case "default":
   228  				cmd := exec.Command("go", "build", "-o", "main.out", ".")
   229  				cmd.Dir = tmpDir
   230  				b, err := cmd.CombinedOutput()
   231  				if err != nil {
   232  					t.Fatalf("build error: %s; OUTPUT:\n%s", err, b)
   233  				}
   234  
   235  				cmd = exec.Command(filepath.Join(tmpDir, "main.out"))
   236  				cmd.Dir = tmpDir
   237  				b, err = cmd.CombinedOutput()
   238  				if err != nil {
   239  					t.Fatalf("run error: %s; OUTPUT:\n%s", err, b)
   240  				}
   241  
   242  			case "none":
   243  
   244  			default:
   245  				t.Errorf("unknown build value %q", tc.build)
   246  			}
   247  
   248  			// only if everthing is golden do we remove
   249  			if !t.Failed() {
   250  				os.RemoveAll(tmpDir)
   251  			}
   252  
   253  		})
   254  	}
   255  
   256  }
   257  
   258  func noFile(p string, t *testing.T) {
   259  	_, err := os.Stat(p)
   260  	if err == nil {
   261  		t.Errorf("file %q should not exist but does", p)
   262  	}
   263  }
   264  
   265  func tstWriteFiles(dir string, m map[string]string) {
   266  
   267  	for name, contents := range m {
   268  		p := filepath.Join(dir, name)
   269  		os.MkdirAll(filepath.Dir(p), 0755)
   270  		err := ioutil.WriteFile(p, []byte(contents), 0644)
   271  		if err != nil {
   272  			panic(err)
   273  		}
   274  	}
   275  
   276  }