github.com/vugu/vugu@v0.3.6-0.20240430171613-3f6f402e014b/staticrender/renderer-static_test.go (about) 1 package staticrender 2 3 import ( 4 "os" 5 "os/exec" 6 "path/filepath" 7 "regexp" 8 "testing" 9 10 "github.com/vugu/vugu/gen" 11 ) 12 13 func TestRendererStaticTable(t *testing.T) { 14 15 debug := false 16 17 vuguDir, err := filepath.Abs("..") 18 if err != nil { 19 t.Fatal(err) 20 } 21 22 type tcase struct { 23 name string 24 opts gen.ParserGoPkgOpts 25 recursive bool 26 infiles map[string]string // file structure to start with 27 outReMatch []string // regexps that must match against output 28 outReNotMatch []string // regexps that must not match against output 29 afterRun func(dir string, t *testing.T) // called after Run 30 bfiles map[string]string // additional files to write before building 31 } 32 33 tcList := []tcase{ 34 { 35 name: "simple", 36 opts: gen.ParserGoPkgOpts{}, 37 recursive: false, 38 infiles: map[string]string{ 39 "root.vugu": `<div>root here</div>`, 40 }, 41 outReMatch: []string{`root here`}, 42 outReNotMatch: []string{`should not match`}, 43 }, 44 { 45 name: "full-html", 46 opts: gen.ParserGoPkgOpts{}, 47 recursive: false, 48 infiles: map[string]string{ 49 "root.vugu": `<html><title vg-if='true'>test title</title><body><div>root here</div></body></html><script src="/a.js"></script>`, 50 }, 51 outReMatch: []string{ 52 `root here`, 53 `<title>test title</title>`, // if statement should have fired 54 `</div><script src="/a.js"></script></body>`, // js should have be written directly inside the body tag 55 }, 56 outReNotMatch: []string{`should not match`}, 57 }, 58 { 59 name: "comp", 60 opts: gen.ParserGoPkgOpts{}, 61 recursive: false, 62 infiles: map[string]string{ 63 "root.vugu": `<html> 64 <head> 65 <title>testing!</title> 66 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"/> 67 <script> 68 console.log("Some script here"); 69 </script> 70 </head> 71 <body> 72 <div> 73 This is a test! 74 Component here: 75 <main:Comp1/> 76 </div> 77 </body> 78 </html>`, 79 "comp1.vugu": `<span> 80 comp1 in the house 81 <div vg-content='vugu.HTML("<p>Some <strong>nested</strong> craziness</p>")'></div> 82 </span>`, 83 }, 84 outReMatch: []string{ 85 `<div><p>Some <strong>nested</strong> craziness</p></div>`, 86 `bootstrap.min.css`, 87 `Some script here`, 88 }, 89 outReNotMatch: []string{`should not match`}, 90 }, 91 { 92 name: "vg-template", 93 opts: gen.ParserGoPkgOpts{}, 94 recursive: false, 95 infiles: map[string]string{ 96 "root.vugu": `<div><span>example1</span><vg-template vg-if='true'>text here</vg-template></div>`, 97 }, 98 outReMatch: []string{ 99 `<span>example1</span>text here`, 100 }, 101 outReNotMatch: []string{`vg-template`}, 102 }, 103 } 104 105 for _, tc := range tcList { 106 tc := tc 107 t.Run(tc.name, func(t *testing.T) { 108 109 tmpDir, err := os.MkdirTemp("", "TestRendererStaticTable") 110 if err != nil { 111 t.Fatal(err) 112 } 113 114 if debug { 115 t.Logf("Test %q using tmpDir: %s", tc.name, tmpDir) 116 } else { 117 t.Parallel() 118 } 119 120 // write a sensible go.mod and main.go, individual tests can override if they really want 121 startf := make(map[string]string, 2) 122 startf["go.mod"] = "module testcase\nreplace github.com/vugu/vugu => " + vuguDir + "\n" 123 startf["main.go"] = `// +build !wasm 124 125 package main 126 127 import ( 128 "os" 129 130 "github.com/vugu/vugu" 131 "github.com/vugu/vugu/staticrender" 132 ) 133 134 func main() { 135 136 rootBuilder := &Root{} 137 138 buildEnv, err := vugu.NewBuildEnv() 139 if err != nil { panic(err) } 140 141 renderer := staticrender.New(os.Stdout) 142 143 buildResults := buildEnv.RunBuild(rootBuilder) 144 145 err = renderer.Render(buildResults) 146 if err != nil { panic(err) } 147 148 } 149 ` 150 tstWriteFiles(tmpDir, startf) 151 152 tstWriteFiles(tmpDir, tc.infiles) 153 154 tc.opts.SkipGoMod = true 155 tc.opts.SkipMainGo = true 156 if tc.recursive { 157 err = gen.RunRecursive(tmpDir, &tc.opts) 158 } else { 159 err = gen.Run(tmpDir, &tc.opts) 160 } 161 if err != nil { 162 t.Fatal(err) 163 } 164 165 if tc.afterRun != nil { 166 tc.afterRun(tmpDir, t) 167 } 168 169 tstWriteFiles(tmpDir, tc.bfiles) 170 171 // build executable for this platform 172 cmd := exec.Command("go", "mod", "tidy") 173 cmd.Dir = tmpDir 174 b, err := cmd.CombinedOutput() 175 if err != nil { 176 t.Fatalf("build error: %s; OUTPUT:\n%s", err, b) 177 } 178 cmd = exec.Command("go", "build", "-o", "main.out", ".") 179 cmd.Dir = tmpDir 180 b, err = cmd.CombinedOutput() 181 if err != nil { 182 t.Fatalf("build error: %s; OUTPUT:\n%s", err, b) 183 } 184 185 // now execute the command and capture the output 186 cmd = exec.Command(filepath.Join(tmpDir, "main.out")) 187 cmd.Dir = tmpDir 188 b, err = cmd.CombinedOutput() 189 if err != nil { 190 t.Fatalf("run error: %s; OUTPUT:\n%s", err, b) 191 } 192 193 // verify the output 194 for _, reTxt := range tc.outReMatch { 195 re := regexp.MustCompile(reTxt) 196 if !re.Match(b) { 197 t.Errorf("Failed to match regexp %q on output", reTxt) 198 } 199 } 200 for _, reTxt := range tc.outReNotMatch { 201 re := regexp.MustCompile(reTxt) 202 if re.Match(b) { 203 t.Errorf("Unexpected match for regexp %q on output", reTxt) 204 } 205 } 206 207 // only if everthing is golden do we remove 208 if !t.Failed() { 209 os.RemoveAll(tmpDir) 210 } else { 211 // and if not then dump the output that was produced 212 t.Logf("FULL OUTPUT:\n%s", b) 213 } 214 215 }) 216 } 217 218 } 219 220 func tstWriteFiles(dir string, m map[string]string) { 221 222 for name, contents := range m { 223 p := filepath.Join(dir, name) 224 err := os.MkdirAll(filepath.Dir(p), 0755) 225 if err != nil { 226 panic(err) 227 } 228 err = os.WriteFile(p, []byte(contents), 0644) 229 if err != nil { 230 panic(err) 231 } 232 } 233 234 } 235 236 // NOTE: this was moved into the table test above 237 // func TestRendererStatic(t *testing.T) { 238 239 // cachekiller := 0 240 // _ = cachekiller 241 242 // // make a temp dir 243 244 // tmpDir, err := os.MkdirTemp("", "TestRendererStatic") 245 // if err != nil { 246 // t.Fatal(err) 247 // } 248 // log.Printf("tmpDir: %s", tmpDir) 249 // // defer os.RemoveAll(tmpDir) 250 251 // wd, err := os.Getwd() 252 // if err != nil { 253 // t.Fatal(err) 254 // } 255 // vuguwd, err := filepath.Abs(filepath.Join(wd, "..")) 256 // if err != nil { 257 // t.Fatal(err) 258 // } 259 260 // // put a go.mod here that points back to the local copy of vugu 261 // err = os.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte(fmt.Sprintf(`module test-render-static 262 // replace github.com/vugu/vugu => %s 263 // require github.com/vugu/vugu v0.0.0-00010101000000-000000000000 264 // `, vuguwd)), 0644) 265 266 // // output some components 267 268 // err = os.WriteFile(filepath.Join(tmpDir, "root.vugu"), []byte(`<html> 269 // <head> 270 // <title>testing!</title> 271 // <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"/> 272 // <script> 273 // console.log("Some script here"); 274 // </script> 275 // </head> 276 // <body> 277 // <div> 278 // This is a test! 279 // Component here: 280 // <main:Comp1/> 281 // </div> 282 // </body> 283 // </html>`), 0644) 284 // if err != nil { 285 // t.Fatal(err) 286 // } 287 288 // err = os.WriteFile(filepath.Join(tmpDir, "comp1.vugu"), []byte(`<span> 289 // comp1 in the house 290 // <div vg-content='vugu.HTML("<p>Some <strong>nested</strong> craziness</p>")'></div> 291 // </span>`), 0644) 292 // if err != nil { 293 // t.Fatal(err) 294 // } 295 296 // // run the vugu codegen 297 298 // p := gen.NewParserGoPkg(tmpDir, nil) 299 // err = p.Run() 300 // if err != nil { 301 // t.Fatal(err) 302 // } 303 304 // // put our static output generation code here 305 306 // err = os.WriteFile(filepath.Join(tmpDir, "staticout.go"), []byte(`// +build !wasm 307 308 // package main 309 310 // import ( 311 // "log" 312 // //"fmt" 313 // "flag" 314 // "os" 315 316 // "github.com/vugu/vugu" 317 // "github.com/vugu/vugu/staticrender" 318 // ) 319 320 // func main() { 321 322 // //mountPoint := flag.String("mount-point", "#vugu_mount_point", "The query selector for the mount point for the root component, if it is not a full HTML component") 323 // flag.Parse() 324 325 // //fmt.Printf("Entering main(), -mount-point=%q\n", *mountPoint) 326 // //defer fmt.Printf("Exiting main()\n") 327 328 // rootBuilder := &Root{} 329 330 // buildEnv, err := vugu.NewBuildEnv() 331 // if err != nil { 332 // log.Fatal(err) 333 // } 334 335 // renderer := staticrender.New(os.Stdout) 336 337 // buildResults := buildEnv.RunBuild(rootBuilder) 338 339 // err = renderer.Render(buildResults) 340 // if err != nil { 341 // panic(err) 342 // } 343 344 // } 345 // `), 0644) 346 // if err != nil { 347 // t.Fatal(err) 348 // } 349 350 // // build it 351 // cmd := exec.Command("go", "build", "-v", "-o", "staticout") 352 // cmd.Dir = tmpDir 353 // b, err := cmd.CombinedOutput() 354 // log.Printf("go build produced:\n%s", b) 355 // if err != nil { 356 // t.Fatal(err) 357 // } 358 359 // // run it and see what it output 360 361 // cmd = exec.Command("./staticout") 362 // cmd.Dir = tmpDir 363 // b, err = cmd.CombinedOutput() 364 // log.Printf("staticout produced:\n%s", b) 365 366 // if err != nil { 367 // t.Fatal(err) 368 // } 369 370 // if !strings.Contains(string(b), "<div><p>Some <strong>nested</strong> craziness</p></div>") { 371 // t.Errorf("falied to find target string in output") 372 // } 373 // if !strings.Contains(string(b), "bootstrap.min.css") { 374 // t.Errorf("falied to find target string in output") 375 // } 376 // if !strings.Contains(string(b), "Some script here") { 377 // t.Errorf("falied to find target string in output") 378 // } 379 380 // }