fckeuspy-go/vendor/fyne.io/fyne/v2/test/app.go

275 lines
5.5 KiB
Go

// Package test provides utility drivers for running UI tests without rendering to a screen.
package test // import "fyne.io/fyne/v2/test"
import (
"net/url"
"sync"
"testing"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/internal"
intapp "fyne.io/fyne/v2/internal/app"
"fyne.io/fyne/v2/internal/cache"
"fyne.io/fyne/v2/internal/painter"
"fyne.io/fyne/v2/internal/test"
"fyne.io/fyne/v2/theme"
)
// ensure we have a dummy app loaded and ready to test
func init() {
NewApp()
}
type app struct {
driver *driver
settings *testSettings
prefs fyne.Preferences
propertyLock sync.RWMutex
storage fyne.Storage
lifecycle intapp.Lifecycle
clip fyne.Clipboard
cloud fyne.CloudProvider
// user action variables
appliedTheme fyne.Theme
lastNotification *fyne.Notification
}
func (a *app) CloudProvider() fyne.CloudProvider {
return a.cloud
}
func (a *app) Icon() fyne.Resource {
return nil
}
func (a *app) SetIcon(fyne.Resource) {
// no-op
}
func (a *app) NewWindow(title string) fyne.Window {
return a.driver.CreateWindow(title)
}
func (a *app) OpenURL(url *url.URL) error {
// no-op
return nil
}
func (a *app) Run() {
// no-op
}
func (a *app) Quit() {
// no-op
}
func (a *app) Clipboard() fyne.Clipboard {
return a.clip
}
func (a *app) UniqueID() string {
return "testApp" // TODO should this be randomised?
}
func (a *app) Driver() fyne.Driver {
return a.driver
}
func (a *app) SendNotification(notify *fyne.Notification) {
a.propertyLock.Lock()
defer a.propertyLock.Unlock()
a.lastNotification = notify
}
func (a *app) SetCloudProvider(p fyne.CloudProvider) {
if p == nil {
a.cloud = nil
return
}
a.transitionCloud(p)
}
func (a *app) Settings() fyne.Settings {
return a.settings
}
func (a *app) Preferences() fyne.Preferences {
return a.prefs
}
func (a *app) Storage() fyne.Storage {
return a.storage
}
func (a *app) Lifecycle() fyne.Lifecycle {
return &a.lifecycle
}
func (a *app) Metadata() fyne.AppMetadata {
return fyne.AppMetadata{} // just dummy data
}
func (a *app) lastAppliedTheme() fyne.Theme {
a.propertyLock.Lock()
defer a.propertyLock.Unlock()
return a.appliedTheme
}
func (a *app) transitionCloud(p fyne.CloudProvider) {
if a.cloud != nil {
a.cloud.Cleanup(a)
}
err := p.Setup(a)
if err != nil {
fyne.LogError("Failed to set up cloud provider "+p.ProviderName(), err)
return
}
a.cloud = p
listeners := a.prefs.ChangeListeners()
if pp, ok := p.(fyne.CloudProviderPreferences); ok {
a.prefs = pp.CloudPreferences(a)
} else {
a.prefs = internal.NewInMemoryPreferences()
}
if store, ok := p.(fyne.CloudProviderStorage); ok {
a.storage = store.CloudStorage(a)
} else {
a.storage = &testStorage{}
}
for _, l := range listeners {
a.prefs.AddChangeListener(l)
l() // assume that preferences have changed because we replaced the provider
}
// after transition ensure settings listener is fired
a.settings.apply()
}
// NewTempApp returns a new dummy app and tears it down at the end of the test.
//
// Since: 2.5
func NewTempApp(t testing.TB) fyne.App {
app := NewApp()
t.Cleanup(func() { NewApp() })
return app
}
// NewApp returns a new dummy app used for testing.
// It loads a test driver which creates a virtual window in memory for testing.
func NewApp() fyne.App {
settings := &testSettings{scale: 1.0, theme: Theme()}
prefs := internal.NewInMemoryPreferences()
store := &testStorage{}
test := &app{settings: settings, prefs: prefs, storage: store, driver: NewDriver().(*driver), clip: NewClipboard()}
settings.app = test
root, _ := store.docRootURI()
store.Docs = &internal.Docs{RootDocURI: root}
painter.ClearFontCache()
cache.ResetThemeCaches()
fyne.SetCurrentApp(test)
return test
}
type testSettings struct {
primaryColor string
scale float32
theme fyne.Theme
listeners []func(fyne.Settings)
changeListeners []chan fyne.Settings
propertyLock sync.RWMutex
app *app
}
func (s *testSettings) AddChangeListener(listener chan fyne.Settings) {
s.propertyLock.Lock()
defer s.propertyLock.Unlock()
s.changeListeners = append(s.changeListeners, listener)
}
func (s *testSettings) AddListener(listener func(fyne.Settings)) {
s.propertyLock.Lock()
defer s.propertyLock.Unlock()
s.listeners = append(s.listeners, listener)
}
func (s *testSettings) BuildType() fyne.BuildType {
return fyne.BuildStandard
}
func (s *testSettings) PrimaryColor() string {
if s.primaryColor != "" {
return s.primaryColor
}
return theme.ColorBlue
}
func (s *testSettings) SetTheme(theme fyne.Theme) {
s.propertyLock.Lock()
s.theme = theme
s.propertyLock.Unlock()
s.apply()
}
func (s *testSettings) ShowAnimations() bool {
return true
}
func (s *testSettings) Theme() fyne.Theme {
s.propertyLock.RLock()
defer s.propertyLock.RUnlock()
if s.theme == nil {
return test.DarkTheme(theme.DefaultTheme())
}
return s.theme
}
func (s *testSettings) ThemeVariant() fyne.ThemeVariant {
return 2 // not a preference
}
func (s *testSettings) Scale() float32 {
s.propertyLock.RLock()
defer s.propertyLock.RUnlock()
return s.scale
}
func (s *testSettings) apply() {
s.propertyLock.RLock()
listeners := s.changeListeners
listenersFns := s.listeners
s.propertyLock.RUnlock()
for _, listener := range listeners {
listener <- s
}
s.app.driver.DoFromGoroutine(func() {
s.app.propertyLock.Lock()
painter.ClearFontCache()
cache.ResetThemeCaches()
intapp.ApplySettings(s, s.app)
s.app.propertyLock.Unlock()
for _, l := range listenersFns {
l(s)
}
}, false)
s.app.propertyLock.Lock()
s.app.appliedTheme = s.Theme()
s.app.propertyLock.Unlock()
}