testsuite/ui/uitest: separate func for browser
The code will be clearer if the browser starting is entirely separate from the testplanet and edge setup. Change-Id: I6d26aa25f4c2a929ba4eda1388234e8aeec518c7
This commit is contained in:
parent
1fdb0eaa5b
commit
aa858a3a23
143
testsuite/ui/uitest/browser.go
Normal file
143
testsuite/ui/uitest/browser.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
package uitest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-rod/rod"
|
||||||
|
"github.com/go-rod/rod/lib/defaults"
|
||||||
|
"github.com/go-rod/rod/lib/launcher"
|
||||||
|
"github.com/go-rod/rod/lib/launcher/flags"
|
||||||
|
"github.com/go-rod/rod/lib/utils"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.uber.org/zap/zaptest"
|
||||||
|
|
||||||
|
"storj.io/common/testcontext"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Our testing suite heavily uses randomly selected ports, which may collide
|
||||||
|
// with the launcher lock port. We'll disable the lock port entirely for
|
||||||
|
// the time being.
|
||||||
|
func init() { defaults.LockPort = 0 }
|
||||||
|
|
||||||
|
// Browser starts a browser for testing using environment variables for configuration.
|
||||||
|
func Browser(t *testing.T, ctx *testcontext.Context, fn func(*rod.Browser)) {
|
||||||
|
showBrowser := os.Getenv("STORJ_TEST_SHOW_BROWSER") != ""
|
||||||
|
slowBrowser := os.Getenv("STORJ_TEST_SHOW_BROWSER") == "slow"
|
||||||
|
|
||||||
|
logLauncher := zaptest.NewLogger(t).Named("launcher")
|
||||||
|
|
||||||
|
browserLoaded := browserTimeoutDetector(10 * time.Second)
|
||||||
|
defer browserLoaded()
|
||||||
|
|
||||||
|
launch := launcher.New().
|
||||||
|
Headless(!showBrowser).
|
||||||
|
Leakless(false).
|
||||||
|
Devtools(false).
|
||||||
|
NoSandbox(true).
|
||||||
|
UserDataDir(ctx.Dir("browser")).
|
||||||
|
Logger(zapWriter{Logger: logLauncher}).
|
||||||
|
Set("enable-logging").
|
||||||
|
Set("disable-gpu")
|
||||||
|
|
||||||
|
if browserHost := os.Getenv("STORJ_TEST_BROWER_HOSTPORT"); browserHost != "" {
|
||||||
|
host, port, err := net.SplitHostPort(browserHost)
|
||||||
|
require.NoError(t, err)
|
||||||
|
launch = launch.Set("remote-debugging-address", host).Set(flags.RemoteDebuggingPort, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
if browserBin := os.Getenv("STORJ_TEST_BROWSER"); browserBin != "" {
|
||||||
|
launch = launch.Bin(browserBin)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
launch.Kill()
|
||||||
|
avoidStall(3*time.Second, launch.Cleanup)
|
||||||
|
}()
|
||||||
|
|
||||||
|
url, err := launch.Launch()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
logBrowser := zaptest.NewLogger(t).Named("rod")
|
||||||
|
|
||||||
|
browser := rod.New().
|
||||||
|
Timeout(time.Minute).
|
||||||
|
Sleeper(func() utils.Sleeper { return timeoutSleeper(5*time.Second, 5) }).
|
||||||
|
ControlURL(url).
|
||||||
|
Logger(utils.Log(func(msg ...interface{}) {
|
||||||
|
logBrowser.Info(fmt.Sprintln(msg...))
|
||||||
|
})).
|
||||||
|
Context(ctx).
|
||||||
|
WithPanic(func(v interface{}) { require.Fail(t, "check failed", v) })
|
||||||
|
|
||||||
|
if slowBrowser {
|
||||||
|
browser = browser.SlowMotion(300 * time.Millisecond).Trace(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer ctx.Check(browser.Close)
|
||||||
|
|
||||||
|
require.NoError(t, browser.Connect())
|
||||||
|
|
||||||
|
browserLoaded()
|
||||||
|
|
||||||
|
fn(browser)
|
||||||
|
}
|
||||||
|
|
||||||
|
func browserTimeoutDetector(duration time.Duration) context.CancelFunc {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
go func() {
|
||||||
|
t := time.NewTimer(duration)
|
||||||
|
defer t.Stop()
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
panic("timeout for starting browser exceeded")
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return cancel
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeoutSleeper(totalSleep time.Duration, maxTries int) utils.Sleeper {
|
||||||
|
singleSleep := totalSleep / time.Duration(maxTries)
|
||||||
|
|
||||||
|
var slept int
|
||||||
|
return func(ctx context.Context) error {
|
||||||
|
slept++
|
||||||
|
if slept > maxTries {
|
||||||
|
return &utils.ErrMaxSleepCount{Max: maxTries}
|
||||||
|
}
|
||||||
|
|
||||||
|
t := time.NewTimer(singleSleep)
|
||||||
|
defer t.Stop()
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
case <-ctx.Done():
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func avoidStall(maxDuration time.Duration, fn func()) {
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
fn()
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
|
||||||
|
timeout := time.NewTicker(maxDuration)
|
||||||
|
defer timeout.Stop()
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
case <-timeout.C:
|
||||||
|
fmt.Printf("go-rod did not shutdown within %v\n", maxDuration)
|
||||||
|
}
|
||||||
|
}
|
@ -4,32 +4,17 @@
|
|||||||
package uitest
|
package uitest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-rod/rod"
|
"github.com/go-rod/rod"
|
||||||
"github.com/go-rod/rod/lib/defaults"
|
|
||||||
"github.com/go-rod/rod/lib/launcher"
|
|
||||||
"github.com/go-rod/rod/lib/launcher/flags"
|
|
||||||
"github.com/go-rod/rod/lib/utils"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"go.uber.org/zap/zaptest"
|
|
||||||
|
|
||||||
"storj.io/common/testcontext"
|
"storj.io/common/testcontext"
|
||||||
"storj.io/storj/private/testplanet"
|
"storj.io/storj/private/testplanet"
|
||||||
"storj.io/storj/satellite"
|
"storj.io/storj/satellite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Our testing suite heavily uses randomly selected ports, which may collide
|
|
||||||
// with the launcher lock port. We'll disable the lock port entirely for
|
|
||||||
// the time being.
|
|
||||||
func init() { defaults.LockPort = 0 }
|
|
||||||
|
|
||||||
// Test defines common services for uitests.
|
// Test defines common services for uitests.
|
||||||
type Test func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet, browser *rod.Browser)
|
type Test func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet, browser *rod.Browser)
|
||||||
|
|
||||||
@ -56,116 +41,8 @@ func Run(t *testing.T, test Test) {
|
|||||||
},
|
},
|
||||||
NonParallel: true,
|
NonParallel: true,
|
||||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||||
showBrowser := os.Getenv("STORJ_TEST_SHOW_BROWSER") != ""
|
Browser(t, ctx, func(browser *rod.Browser) {
|
||||||
slowBrowser := os.Getenv("STORJ_TEST_SHOW_BROWSER") == "slow"
|
test(t, ctx, planet, browser)
|
||||||
|
})
|
||||||
logLauncher := zaptest.NewLogger(t).Named("launcher")
|
|
||||||
|
|
||||||
browserLoaded := browserTimeoutDetector(10 * time.Second)
|
|
||||||
defer browserLoaded()
|
|
||||||
|
|
||||||
launch := launcher.New().
|
|
||||||
Headless(!showBrowser).
|
|
||||||
Leakless(false).
|
|
||||||
Devtools(false).
|
|
||||||
NoSandbox(true).
|
|
||||||
UserDataDir(ctx.Dir("browser")).
|
|
||||||
Logger(zapWriter{Logger: logLauncher}).
|
|
||||||
Set("enable-logging").
|
|
||||||
Set("disable-gpu")
|
|
||||||
|
|
||||||
if browserHost := os.Getenv("STORJ_TEST_BROWER_HOSTPORT"); browserHost != "" {
|
|
||||||
host, port, err := net.SplitHostPort(browserHost)
|
|
||||||
require.NoError(t, err)
|
|
||||||
launch = launch.Set("remote-debugging-address", host).Set(flags.RemoteDebuggingPort, port)
|
|
||||||
}
|
|
||||||
|
|
||||||
if browserBin := os.Getenv("STORJ_TEST_BROWSER"); browserBin != "" {
|
|
||||||
launch = launch.Bin(browserBin)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
launch.Kill()
|
|
||||||
avoidStall(3*time.Second, launch.Cleanup)
|
|
||||||
}()
|
|
||||||
|
|
||||||
url, err := launch.Launch()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
logBrowser := zaptest.NewLogger(t).Named("rod")
|
|
||||||
|
|
||||||
browser := rod.New().
|
|
||||||
Timeout(time.Minute).
|
|
||||||
Sleeper(func() utils.Sleeper { return timeoutSleeper(5*time.Second, 5) }).
|
|
||||||
ControlURL(url).
|
|
||||||
Logger(utils.Log(func(msg ...interface{}) {
|
|
||||||
logBrowser.Info(fmt.Sprintln(msg...))
|
|
||||||
})).
|
|
||||||
Context(ctx).
|
|
||||||
WithPanic(func(v interface{}) { require.Fail(t, "check failed", v) })
|
|
||||||
|
|
||||||
if slowBrowser {
|
|
||||||
browser = browser.SlowMotion(300 * time.Millisecond).Trace(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer ctx.Check(browser.Close)
|
|
||||||
|
|
||||||
require.NoError(t, browser.Connect())
|
|
||||||
|
|
||||||
browserLoaded()
|
|
||||||
|
|
||||||
test(t, ctx, planet, browser)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func browserTimeoutDetector(duration time.Duration) context.CancelFunc {
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
go func() {
|
|
||||||
t := time.NewTimer(duration)
|
|
||||||
defer t.Stop()
|
|
||||||
select {
|
|
||||||
case <-t.C:
|
|
||||||
panic("timeout for starting browser exceeded")
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return cancel
|
|
||||||
}
|
|
||||||
|
|
||||||
func timeoutSleeper(totalSleep time.Duration, maxTries int) utils.Sleeper {
|
|
||||||
singleSleep := totalSleep / time.Duration(maxTries)
|
|
||||||
|
|
||||||
var slept int
|
|
||||||
return func(ctx context.Context) error {
|
|
||||||
slept++
|
|
||||||
if slept > maxTries {
|
|
||||||
return &utils.ErrMaxSleepCount{Max: maxTries}
|
|
||||||
}
|
|
||||||
|
|
||||||
t := time.NewTimer(singleSleep)
|
|
||||||
defer t.Stop()
|
|
||||||
select {
|
|
||||||
case <-t.C:
|
|
||||||
case <-ctx.Done():
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func avoidStall(maxDuration time.Duration, fn func()) {
|
|
||||||
done := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
fn()
|
|
||||||
close(done)
|
|
||||||
}()
|
|
||||||
|
|
||||||
timeout := time.NewTicker(maxDuration)
|
|
||||||
defer timeout.Stop()
|
|
||||||
select {
|
|
||||||
case <-done:
|
|
||||||
case <-timeout.C:
|
|
||||||
fmt.Printf("go-rod did not shutdown within %v\n", maxDuration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user