github.com/cybriq/giocore@v0.0.7-0.20210703034601-cfb9cb5f3900/cmd/gogio/js_test.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package main_test 4 5 import ( 6 "bytes" 7 "context" 8 "errors" 9 "image" 10 "image/png" 11 "io" 12 "net/http" 13 "net/http/httptest" 14 "os/exec" 15 16 "github.com/chromedp/cdproto/runtime" 17 "github.com/chromedp/chromedp" 18 19 _ "github.com/cybriq/giocore/unit" // the build tool adds it to go.mod, so keep it there 20 ) 21 22 type JSTestDriver struct { 23 driverBase 24 25 // ctx is the chromedp context. 26 ctx context.Context 27 } 28 29 func (d *JSTestDriver) Start(path string) { 30 if raceEnabled { 31 d.Skipf("js/wasm doesn't support -race; skipping") 32 } 33 34 // First, build the app. 35 dir := d.tempDir("gio-endtoend-js") 36 d.gogio("-target=js", "-o="+dir, path) 37 38 // Second, start Chrome. 39 opts := append(chromedp.DefaultExecAllocatorOptions[:], 40 chromedp.Flag("headless", *headless), 41 ) 42 43 actx, cancel := chromedp.NewExecAllocator(context.Background(), opts...) 44 d.Cleanup(cancel) 45 46 ctx, cancel := chromedp.NewContext(actx, 47 // Send all logf/errf calls to t.Logf 48 chromedp.WithLogf(d.Logf), 49 ) 50 d.Cleanup(cancel) 51 d.ctx = ctx 52 53 if err := chromedp.Run(ctx); err != nil { 54 if errors.Is(err, exec.ErrNotFound) { 55 d.Skipf("test requires Chrome to be installed: %v", err) 56 return 57 } 58 d.Fatal(err) 59 } 60 pr, pw := io.Pipe() 61 d.Cleanup(func() { pw.Close() }) 62 d.output = pr 63 chromedp.ListenTarget(ctx, func(ev interface{}) { 64 switch ev := ev.(type) { 65 case *runtime.EventConsoleAPICalled: 66 switch ev.Type { 67 case "log", "info", "warning", "error": 68 var b bytes.Buffer 69 b.WriteString("console.") 70 b.WriteString(string(ev.Type)) 71 b.WriteString("(") 72 for i, arg := range ev.Args { 73 if i > 0 { 74 b.WriteString(", ") 75 } 76 b.Write(arg.Value) 77 } 78 b.WriteString(")\n") 79 pw.Write(b.Bytes()) 80 } 81 } 82 }) 83 84 // Third, serve the app folder, set the browser tab dimensions, and 85 // navigate to the folder. 86 ts := httptest.NewServer(http.FileServer(http.Dir(dir))) 87 d.Cleanup(ts.Close) 88 89 if err := chromedp.Run(ctx, 90 chromedp.EmulateViewport(int64(d.width), int64(d.height)), 91 chromedp.Navigate(ts.URL), 92 ); err != nil { 93 d.Fatal(err) 94 } 95 96 // Wait for the gio app to render. 97 d.waitForFrame() 98 } 99 100 func (d *JSTestDriver) Screenshot() image.Image { 101 var buf []byte 102 if err := chromedp.Run(d.ctx, 103 chromedp.CaptureScreenshot(&buf), 104 ); err != nil { 105 d.Fatal(err) 106 } 107 img, err := png.Decode(bytes.NewReader(buf)) 108 if err != nil { 109 d.Fatal(err) 110 } 111 return img 112 } 113 114 func (d *JSTestDriver) Click(x, y int) { 115 if err := chromedp.Run(d.ctx, 116 chromedp.MouseClickXY(float64(x), float64(y)), 117 ); err != nil { 118 d.Fatal(err) 119 } 120 121 // Wait for the gio app to render after this click. 122 d.waitForFrame() 123 }