mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
4641607cd6
For example, if the browser doesn't have webgl at all, the gio app will fail to load. This will result in the screenshot being incorrect, without an apparent reason: --- FAIL: TestJSOnChrome (0.89s) js_test.go:122: got 0xffffffffffffffff at (5,5), want 0xffff00000000ffff js_test.go:122: got 0xffffffffffffffff at (595,595), want 0xffff00000000ffff The underlying webgl error was accessible if one added a sleep and ran 'go test -headless=false', allowing to open the console and see the error messages. Instead, capture them via chromedp and print them to the test's logger: --- FAIL: TestJSOnChrome (0.89s) js_test.go:79: console log: "2019/10/29 12:41:07 app: webgl is not supported" js_test.go:79: console warning: "exit code:", 1 js_test.go:122: got 0xffffffffffffffff at (5,5), want 0xffff00000000ffff js_test.go:122: got 0xffffffffffffffff at (595,595), want 0xffff00000000ffff JS Exceptions are a completely different mechanism, so they're not covered by this patch. We can add them at a later time if needed. While at it, update to the latest tagged version of chromedp. Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
129 lines
3.4 KiB
Go
129 lines
3.4 KiB
Go
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
package main_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"flag"
|
|
"image/png"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/chromedp/cdproto/runtime"
|
|
"github.com/chromedp/chromedp"
|
|
|
|
_ "gioui.org/unit" // the build tool adds it to go.mod, so keep it there
|
|
)
|
|
|
|
var headless = flag.Bool("headless", true, "run end-to-end tests in headless mode")
|
|
|
|
func TestJSOnChrome(t *testing.T) {
|
|
// First, build the app.
|
|
dir, err := ioutil.TempDir("", "gio-endtoend-js")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
// TODO(mvdan): This is inefficient, as we link the gogio tool every time.
|
|
// Consider options in the future. On the plus side, this is simple.
|
|
cmd := exec.Command("go", "run", ".", "-target=js", "-o="+dir, "testdata/red.go")
|
|
if out, err := cmd.CombinedOutput(); err != nil {
|
|
t.Fatalf("could not build app: %s:\n%s", err, out)
|
|
}
|
|
|
|
// Second, start Chrome.
|
|
opts := append(chromedp.DefaultExecAllocatorOptions[:],
|
|
chromedp.Flag("headless", *headless),
|
|
|
|
// We need use-gl=egl instead of the default of use-gl=desktop;
|
|
// "desktop" doesn't seem to work when we're in headless mode.
|
|
// TODO(mvdan): Does egl require a GPU? If so, consider
|
|
// use-gl=swiftshader, which will use CPU-based rendering. That
|
|
// might be necessary for some CI or headless environments.
|
|
chromedp.Flag("use-gl", "egl"),
|
|
)
|
|
|
|
actx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
|
|
defer cancel()
|
|
|
|
ctx, cancel := chromedp.NewContext(actx)
|
|
defer cancel()
|
|
|
|
if err := chromedp.Run(ctx); err != nil {
|
|
if errors.Is(err, exec.ErrNotFound) {
|
|
t.Skipf("test requires Chrome to be installed: %v", err)
|
|
return
|
|
}
|
|
t.Fatal(err)
|
|
}
|
|
chromedp.ListenTarget(ctx, func(ev interface{}) {
|
|
switch ev := ev.(type) {
|
|
case *runtime.EventConsoleAPICalled:
|
|
switch ev.Type {
|
|
case "log", "info", "warning", "error":
|
|
var args strings.Builder
|
|
for i, arg := range ev.Args {
|
|
if i > 0 {
|
|
args.WriteString(", ")
|
|
}
|
|
args.Write(arg.Value)
|
|
}
|
|
t.Logf("console %s: %s", ev.Type, args.String())
|
|
}
|
|
}
|
|
})
|
|
|
|
// Third, serve the app folder, set the browser tab dimensions, and
|
|
// navigate to the folder.
|
|
ts := httptest.NewServer(http.FileServer(http.Dir(dir)))
|
|
defer ts.Close()
|
|
|
|
if err := chromedp.Run(ctx,
|
|
// A small window with 2x HiDPI.
|
|
chromedp.EmulateViewport(300, 300, chromedp.EmulateScale(2.0)),
|
|
chromedp.Navigate(ts.URL),
|
|
); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Finally, run the test.
|
|
|
|
// 1: Once the canvas is ready, grab a screenshot to check that the
|
|
// entirety of the viewport is red, as per the background color.
|
|
var buf []byte
|
|
if err := chromedp.Run(ctx,
|
|
chromedp.WaitReady("canvas", chromedp.ByQuery),
|
|
chromedp.CaptureScreenshot(&buf),
|
|
); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
img, err := png.Decode(bytes.NewReader(buf))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
size := img.Bounds().Size()
|
|
wantSize := 600 // 300px at 2.0 scaling factor
|
|
if size.X != wantSize || size.Y != wantSize {
|
|
t.Fatalf("expected dimensions to be %d*%d, got %d*%d",
|
|
wantSize, wantSize, size.X, size.Y)
|
|
}
|
|
wantColor := func(x, y int, r, g, b, a uint32) {
|
|
color := img.At(x, y)
|
|
r_, g_, b_, a_ := color.RGBA()
|
|
if r_ != r || g_ != g || b_ != b || a_ != a {
|
|
t.Errorf("got 0x%04x%04x%04x%04x at (%d,%d), want 0x%04x%04x%04x%04x",
|
|
r_, g_, b_, a_, x, y, r, g, b, a)
|
|
}
|
|
}
|
|
wantColor(5, 5, 0xffff, 0x0, 0x0, 0xffff)
|
|
wantColor(595, 595, 0xffff, 0x0, 0x0, 0xffff)
|
|
}
|