788 lines
21 KiB
Go
788 lines
21 KiB
Go
package playwright
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
mapset "github.com/deckarep/golang-set/v2"
|
|
)
|
|
|
|
type frameImpl struct {
|
|
channelOwner
|
|
detached bool
|
|
page *pageImpl
|
|
name string
|
|
url string
|
|
parentFrame Frame
|
|
childFrames []Frame
|
|
loadStates mapset.Set[string]
|
|
}
|
|
|
|
func newFrame(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *frameImpl {
|
|
var loadStates mapset.Set[string]
|
|
|
|
if ls, ok := initializer["loadStates"].([]string); ok {
|
|
loadStates = mapset.NewSet[string](ls...)
|
|
} else {
|
|
loadStates = mapset.NewSet[string]()
|
|
}
|
|
f := &frameImpl{
|
|
name: initializer["name"].(string),
|
|
url: initializer["url"].(string),
|
|
loadStates: loadStates,
|
|
childFrames: make([]Frame, 0),
|
|
}
|
|
f.createChannelOwner(f, parent, objectType, guid, initializer)
|
|
|
|
channelOwner := fromNullableChannel(initializer["parentFrame"])
|
|
if channelOwner != nil {
|
|
f.parentFrame = channelOwner.(*frameImpl)
|
|
f.parentFrame.(*frameImpl).childFrames = append(f.parentFrame.(*frameImpl).childFrames, f)
|
|
}
|
|
|
|
f.channel.On("navigated", f.onFrameNavigated)
|
|
f.channel.On("loadstate", f.onLoadState)
|
|
return f
|
|
}
|
|
|
|
func (f *frameImpl) URL() string {
|
|
f.RLock()
|
|
defer f.RUnlock()
|
|
return f.url
|
|
}
|
|
|
|
func (f *frameImpl) Name() string {
|
|
f.RLock()
|
|
defer f.RUnlock()
|
|
return f.name
|
|
}
|
|
|
|
func (f *frameImpl) SetContent(content string, options ...FrameSetContentOptions) error {
|
|
_, err := f.channel.Send("setContent", map[string]interface{}{
|
|
"html": content,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) Content() (string, error) {
|
|
content, err := f.channel.Send("content")
|
|
if content == nil {
|
|
return "", err
|
|
}
|
|
return content.(string), err
|
|
}
|
|
|
|
func (f *frameImpl) Goto(url string, options ...FrameGotoOptions) (Response, error) {
|
|
channel, err := f.channel.Send("goto", map[string]interface{}{
|
|
"url": url,
|
|
}, options)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Frame.Goto %s: %w", url, err)
|
|
}
|
|
channelOwner := fromNullableChannel(channel)
|
|
if channelOwner == nil {
|
|
// navigation to about:blank or navigation to the same URL with a different hash
|
|
return nil, nil
|
|
}
|
|
return channelOwner.(*responseImpl), nil
|
|
}
|
|
|
|
func (f *frameImpl) AddScriptTag(options FrameAddScriptTagOptions) (ElementHandle, error) {
|
|
if options.Path != nil {
|
|
file, err := os.ReadFile(*options.Path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
options.Content = String(string(file))
|
|
options.Path = nil
|
|
}
|
|
channel, err := f.channel.Send("addScriptTag", options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return fromChannel(channel).(*elementHandleImpl), nil
|
|
}
|
|
|
|
func (f *frameImpl) AddStyleTag(options FrameAddStyleTagOptions) (ElementHandle, error) {
|
|
if options.Path != nil {
|
|
file, err := os.ReadFile(*options.Path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
options.Content = String(string(file))
|
|
options.Path = nil
|
|
}
|
|
channel, err := f.channel.Send("addStyleTag", options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return fromChannel(channel).(*elementHandleImpl), nil
|
|
}
|
|
|
|
func (f *frameImpl) Page() Page {
|
|
return f.page
|
|
}
|
|
|
|
func (f *frameImpl) WaitForLoadState(options ...FrameWaitForLoadStateOptions) error {
|
|
option := FrameWaitForLoadStateOptions{}
|
|
if len(options) == 1 {
|
|
option = options[0]
|
|
}
|
|
if option.State == nil {
|
|
option.State = LoadStateLoad
|
|
}
|
|
return f.waitForLoadStateImpl(string(*option.State), option.Timeout, nil)
|
|
}
|
|
|
|
func (f *frameImpl) waitForLoadStateImpl(state string, timeout *float64, cb func() error) error {
|
|
if f.loadStates.ContainsOne(state) {
|
|
return nil
|
|
}
|
|
waiter, err := f.setNavigationWaiter(timeout)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
waiter.WaitForEvent(f, "loadstate", func(payload interface{}) bool {
|
|
gotState := payload.(string)
|
|
return gotState == state
|
|
})
|
|
if cb == nil {
|
|
_, err := waiter.Wait()
|
|
return err
|
|
} else {
|
|
_, err := waiter.RunAndWait(cb)
|
|
return err
|
|
}
|
|
}
|
|
|
|
func (f *frameImpl) WaitForURL(url interface{}, options ...FrameWaitForURLOptions) error {
|
|
if f.page == nil {
|
|
return errors.New("frame is detached")
|
|
}
|
|
matcher := newURLMatcher(url, f.page.browserContext.options.BaseURL)
|
|
if matcher.Matches(f.URL()) {
|
|
state := "load"
|
|
timeout := Float(f.page.timeoutSettings.NavigationTimeout())
|
|
if len(options) == 1 {
|
|
if options[0].WaitUntil != nil {
|
|
state = string(*options[0].WaitUntil)
|
|
}
|
|
if options[0].Timeout != nil {
|
|
timeout = options[0].Timeout
|
|
}
|
|
}
|
|
return f.waitForLoadStateImpl(state, timeout, nil)
|
|
}
|
|
navigationOptions := FrameExpectNavigationOptions{URL: url}
|
|
if len(options) > 0 {
|
|
navigationOptions.Timeout = options[0].Timeout
|
|
navigationOptions.WaitUntil = options[0].WaitUntil
|
|
}
|
|
if _, err := f.ExpectNavigation(nil, navigationOptions); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (f *frameImpl) ExpectNavigation(cb func() error, options ...FrameExpectNavigationOptions) (Response, error) {
|
|
if f.page == nil {
|
|
return nil, errors.New("frame is detached")
|
|
}
|
|
option := FrameExpectNavigationOptions{}
|
|
if len(options) == 1 {
|
|
option = options[0]
|
|
}
|
|
if option.WaitUntil == nil {
|
|
option.WaitUntil = WaitUntilStateLoad
|
|
}
|
|
if option.Timeout == nil {
|
|
option.Timeout = Float(f.page.timeoutSettings.NavigationTimeout())
|
|
}
|
|
deadline := time.Now().Add(time.Duration(*option.Timeout) * time.Millisecond)
|
|
var matcher *urlMatcher
|
|
if option.URL != nil {
|
|
matcher = newURLMatcher(option.URL, f.page.browserContext.options.BaseURL)
|
|
}
|
|
predicate := func(events ...interface{}) bool {
|
|
ev := events[0].(map[string]interface{})
|
|
err, ok := ev["error"]
|
|
if ok {
|
|
// Any failed navigation results in a rejection.
|
|
logger.Error("navigation error", "url", ev["url"].(string), "error", err)
|
|
return true
|
|
}
|
|
return matcher == nil || matcher.Matches(ev["url"].(string))
|
|
}
|
|
waiter, err := f.setNavigationWaiter(option.Timeout)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
eventData, err := waiter.WaitForEvent(f, "navigated", predicate).RunAndWait(cb)
|
|
if err != nil || eventData == nil {
|
|
return nil, err
|
|
}
|
|
|
|
t := time.Until(deadline).Milliseconds()
|
|
if t > 0 {
|
|
err = f.waitForLoadStateImpl(string(*option.WaitUntil), Float(float64(t)), nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
event := eventData.(map[string]interface{})
|
|
if event["newDocument"] != nil && event["newDocument"].(map[string]interface{})["request"] != nil {
|
|
request := fromChannel(event["newDocument"].(map[string]interface{})["request"]).(*requestImpl)
|
|
return request.Response()
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (f *frameImpl) setNavigationWaiter(timeout *float64) (*waiter, error) {
|
|
if f.page == nil {
|
|
return nil, errors.New("page does not exist")
|
|
}
|
|
waiter := newWaiter()
|
|
if timeout != nil {
|
|
waiter.WithTimeout(*timeout)
|
|
} else {
|
|
waiter.WithTimeout(f.page.timeoutSettings.NavigationTimeout())
|
|
}
|
|
waiter.RejectOnEvent(f.page, "close", f.page.closeErrorWithReason())
|
|
waiter.RejectOnEvent(f.page, "crash", fmt.Errorf("Navigation failed because page crashed!"))
|
|
waiter.RejectOnEvent(f.page, "framedetached", fmt.Errorf("Navigating frame was detached!"), func(payload interface{}) bool {
|
|
frame, ok := payload.(*frameImpl)
|
|
if ok && frame == f {
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
return waiter, nil
|
|
}
|
|
|
|
func (f *frameImpl) onFrameNavigated(ev map[string]interface{}) {
|
|
f.Lock()
|
|
f.url = ev["url"].(string)
|
|
f.name = ev["name"].(string)
|
|
f.Unlock()
|
|
f.Emit("navigated", ev)
|
|
_, ok := ev["error"]
|
|
if !ok && f.page != nil {
|
|
f.page.Emit("framenavigated", f)
|
|
}
|
|
}
|
|
|
|
func (f *frameImpl) onLoadState(ev map[string]interface{}) {
|
|
if ev["add"] != nil {
|
|
add := ev["add"].(string)
|
|
f.loadStates.Add(add)
|
|
f.Emit("loadstate", add)
|
|
if f.parentFrame == nil && f.page != nil {
|
|
if add == "load" || add == "domcontentloaded" {
|
|
f.Page().Emit(add, f.page)
|
|
}
|
|
}
|
|
} else if ev["remove"] != nil {
|
|
remove := ev["remove"].(string)
|
|
f.loadStates.Remove(remove)
|
|
}
|
|
}
|
|
|
|
func (f *frameImpl) QuerySelector(selector string, options ...FrameQuerySelectorOptions) (ElementHandle, error) {
|
|
params := map[string]interface{}{
|
|
"selector": selector,
|
|
}
|
|
if len(options) == 1 {
|
|
params["strict"] = options[0].Strict
|
|
}
|
|
channel, err := f.channel.Send("querySelector", params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if channel == nil {
|
|
return nil, nil
|
|
}
|
|
return fromChannel(channel).(*elementHandleImpl), nil
|
|
}
|
|
|
|
func (f *frameImpl) QuerySelectorAll(selector string) ([]ElementHandle, error) {
|
|
channels, err := f.channel.Send("querySelectorAll", map[string]interface{}{
|
|
"selector": selector,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
elements := make([]ElementHandle, 0)
|
|
for _, channel := range channels.([]interface{}) {
|
|
elements = append(elements, fromChannel(channel).(*elementHandleImpl))
|
|
}
|
|
return elements, nil
|
|
}
|
|
|
|
func (f *frameImpl) Evaluate(expression string, options ...interface{}) (interface{}, error) {
|
|
var arg interface{}
|
|
if len(options) == 1 {
|
|
arg = options[0]
|
|
}
|
|
result, err := f.channel.Send("evaluateExpression", map[string]interface{}{
|
|
"expression": expression,
|
|
"arg": serializeArgument(arg),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return parseResult(result), nil
|
|
}
|
|
|
|
func (f *frameImpl) EvalOnSelector(selector string, expression string, arg interface{}, options ...FrameEvalOnSelectorOptions) (interface{}, error) {
|
|
params := map[string]interface{}{
|
|
"selector": selector,
|
|
"expression": expression,
|
|
"arg": serializeArgument(arg),
|
|
}
|
|
if len(options) == 1 && options[0].Strict != nil {
|
|
params["strict"] = *options[0].Strict
|
|
}
|
|
|
|
result, err := f.channel.Send("evalOnSelector", params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return parseResult(result), nil
|
|
}
|
|
|
|
func (f *frameImpl) EvalOnSelectorAll(selector string, expression string, options ...interface{}) (interface{}, error) {
|
|
var arg interface{}
|
|
if len(options) == 1 {
|
|
arg = options[0]
|
|
}
|
|
result, err := f.channel.Send("evalOnSelectorAll", map[string]interface{}{
|
|
"selector": selector,
|
|
"expression": expression,
|
|
"arg": serializeArgument(arg),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return parseResult(result), nil
|
|
}
|
|
|
|
func (f *frameImpl) EvaluateHandle(expression string, options ...interface{}) (JSHandle, error) {
|
|
var arg interface{}
|
|
if len(options) == 1 {
|
|
arg = options[0]
|
|
}
|
|
result, err := f.channel.Send("evaluateExpressionHandle", map[string]interface{}{
|
|
"expression": expression,
|
|
"arg": serializeArgument(arg),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
channelOwner := fromChannel(result)
|
|
if channelOwner == nil {
|
|
return nil, nil
|
|
}
|
|
return channelOwner.(JSHandle), nil
|
|
}
|
|
|
|
func (f *frameImpl) Click(selector string, options ...FrameClickOptions) error {
|
|
_, err := f.channel.Send("click", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) WaitForSelector(selector string, options ...FrameWaitForSelectorOptions) (ElementHandle, error) {
|
|
channel, err := f.channel.Send("waitForSelector", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
channelOwner := fromNullableChannel(channel)
|
|
if channelOwner == nil {
|
|
return nil, nil
|
|
}
|
|
return channelOwner.(*elementHandleImpl), nil
|
|
}
|
|
|
|
func (f *frameImpl) DispatchEvent(selector, typ string, eventInit interface{}, options ...FrameDispatchEventOptions) error {
|
|
_, err := f.channel.Send("dispatchEvent", map[string]interface{}{
|
|
"selector": selector,
|
|
"type": typ,
|
|
"eventInit": serializeArgument(eventInit),
|
|
})
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) InnerText(selector string, options ...FrameInnerTextOptions) (string, error) {
|
|
innerText, err := f.channel.Send("innerText", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if innerText == nil {
|
|
return "", err
|
|
}
|
|
return innerText.(string), err
|
|
}
|
|
|
|
func (f *frameImpl) InnerHTML(selector string, options ...FrameInnerHTMLOptions) (string, error) {
|
|
innerHTML, err := f.channel.Send("innerHTML", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if innerHTML == nil {
|
|
return "", err
|
|
}
|
|
return innerHTML.(string), err
|
|
}
|
|
|
|
func (f *frameImpl) GetAttribute(selector string, name string, options ...FrameGetAttributeOptions) (string, error) {
|
|
attribute, err := f.channel.Send("getAttribute", map[string]interface{}{
|
|
"selector": selector,
|
|
"name": name,
|
|
}, options)
|
|
if attribute == nil {
|
|
return "", err
|
|
}
|
|
return attribute.(string), err
|
|
}
|
|
|
|
func (f *frameImpl) Hover(selector string, options ...FrameHoverOptions) error {
|
|
_, err := f.channel.Send("hover", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) SetInputFiles(selector string, files interface{}, options ...FrameSetInputFilesOptions) error {
|
|
params, err := convertInputFiles(files, f.page.browserContext)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
params.Selector = &selector
|
|
_, err = f.channel.Send("setInputFiles", params, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) Type(selector, text string, options ...FrameTypeOptions) error {
|
|
_, err := f.channel.Send("type", map[string]interface{}{
|
|
"selector": selector,
|
|
"text": text,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) Press(selector, key string, options ...FramePressOptions) error {
|
|
_, err := f.channel.Send("press", map[string]interface{}{
|
|
"selector": selector,
|
|
"key": key,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) Check(selector string, options ...FrameCheckOptions) error {
|
|
_, err := f.channel.Send("check", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) Uncheck(selector string, options ...FrameUncheckOptions) error {
|
|
_, err := f.channel.Send("uncheck", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) WaitForTimeout(timeout float64) {
|
|
time.Sleep(time.Duration(timeout) * time.Millisecond)
|
|
}
|
|
|
|
func (f *frameImpl) WaitForFunction(expression string, arg interface{}, options ...FrameWaitForFunctionOptions) (JSHandle, error) {
|
|
var option FrameWaitForFunctionOptions
|
|
if len(options) == 1 {
|
|
option = options[0]
|
|
}
|
|
result, err := f.channel.Send("waitForFunction", map[string]interface{}{
|
|
"expression": expression,
|
|
"arg": serializeArgument(arg),
|
|
"timeout": option.Timeout,
|
|
"polling": option.Polling,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
handle := fromChannel(result)
|
|
if handle == nil {
|
|
return nil, nil
|
|
}
|
|
return handle.(*jsHandleImpl), nil
|
|
}
|
|
|
|
func (f *frameImpl) Title() (string, error) {
|
|
title, err := f.channel.Send("title")
|
|
if title == nil {
|
|
return "", err
|
|
}
|
|
return title.(string), err
|
|
}
|
|
|
|
func (f *frameImpl) ChildFrames() []Frame {
|
|
return f.childFrames
|
|
}
|
|
|
|
func (f *frameImpl) Dblclick(selector string, options ...FrameDblclickOptions) error {
|
|
_, err := f.channel.Send("dblclick", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) Fill(selector string, value string, options ...FrameFillOptions) error {
|
|
_, err := f.channel.Send("fill", map[string]interface{}{
|
|
"selector": selector,
|
|
"value": value,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) Focus(selector string, options ...FrameFocusOptions) error {
|
|
_, err := f.channel.Send("focus", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) FrameElement() (ElementHandle, error) {
|
|
channel, err := f.channel.Send("frameElement")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return fromChannel(channel).(*elementHandleImpl), nil
|
|
}
|
|
|
|
func (f *frameImpl) IsDetached() bool {
|
|
return f.detached
|
|
}
|
|
|
|
func (f *frameImpl) ParentFrame() Frame {
|
|
return f.parentFrame
|
|
}
|
|
|
|
func (f *frameImpl) TextContent(selector string, options ...FrameTextContentOptions) (string, error) {
|
|
textContent, err := f.channel.Send("textContent", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if textContent == nil {
|
|
return "", err
|
|
}
|
|
return textContent.(string), err
|
|
}
|
|
|
|
func (f *frameImpl) Tap(selector string, options ...FrameTapOptions) error {
|
|
_, err := f.channel.Send("tap", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) SelectOption(selector string, values SelectOptionValues, options ...FrameSelectOptionOptions) ([]string, error) {
|
|
opts := convertSelectOptionSet(values)
|
|
|
|
m := make(map[string]interface{})
|
|
m["selector"] = selector
|
|
for k, v := range opts {
|
|
m[k] = v
|
|
}
|
|
selected, err := f.channel.Send("selectOption", m, options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return transformToStringList(selected), nil
|
|
}
|
|
|
|
func (f *frameImpl) IsChecked(selector string, options ...FrameIsCheckedOptions) (bool, error) {
|
|
checked, err := f.channel.Send("isChecked", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return checked.(bool), nil
|
|
}
|
|
|
|
func (f *frameImpl) IsDisabled(selector string, options ...FrameIsDisabledOptions) (bool, error) {
|
|
disabled, err := f.channel.Send("isDisabled", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return disabled.(bool), nil
|
|
}
|
|
|
|
func (f *frameImpl) IsEditable(selector string, options ...FrameIsEditableOptions) (bool, error) {
|
|
editable, err := f.channel.Send("isEditable", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return editable.(bool), nil
|
|
}
|
|
|
|
func (f *frameImpl) IsEnabled(selector string, options ...FrameIsEnabledOptions) (bool, error) {
|
|
enabled, err := f.channel.Send("isEnabled", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return enabled.(bool), nil
|
|
}
|
|
|
|
func (f *frameImpl) IsHidden(selector string, options ...FrameIsHiddenOptions) (bool, error) {
|
|
hidden, err := f.channel.Send("isHidden", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return hidden.(bool), nil
|
|
}
|
|
|
|
func (f *frameImpl) IsVisible(selector string, options ...FrameIsVisibleOptions) (bool, error) {
|
|
visible, err := f.channel.Send("isVisible", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return visible.(bool), nil
|
|
}
|
|
|
|
func (f *frameImpl) InputValue(selector string, options ...FrameInputValueOptions) (string, error) {
|
|
value, err := f.channel.Send("inputValue", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
if value == nil {
|
|
return "", err
|
|
}
|
|
return value.(string), err
|
|
}
|
|
|
|
func (f *frameImpl) DragAndDrop(source, target string, options ...FrameDragAndDropOptions) error {
|
|
_, err := f.channel.Send("dragAndDrop", map[string]interface{}{
|
|
"source": source,
|
|
"target": target,
|
|
}, options)
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) SetChecked(selector string, checked bool, options ...FrameSetCheckedOptions) error {
|
|
if checked {
|
|
_, err := f.channel.Send("check", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
return err
|
|
} else {
|
|
_, err := f.channel.Send("uncheck", map[string]interface{}{
|
|
"selector": selector,
|
|
}, options)
|
|
return err
|
|
}
|
|
}
|
|
|
|
func (f *frameImpl) Locator(selector string, options ...FrameLocatorOptions) Locator {
|
|
var option LocatorLocatorOptions
|
|
if len(options) == 1 {
|
|
option = LocatorLocatorOptions(options[0])
|
|
}
|
|
return newLocator(f, selector, option)
|
|
}
|
|
|
|
func (f *frameImpl) GetByAltText(text interface{}, options ...FrameGetByAltTextOptions) Locator {
|
|
exact := false
|
|
if len(options) == 1 {
|
|
if *options[0].Exact {
|
|
exact = true
|
|
}
|
|
}
|
|
return f.Locator(getByAltTextSelector(text, exact))
|
|
}
|
|
|
|
func (f *frameImpl) GetByLabel(text interface{}, options ...FrameGetByLabelOptions) Locator {
|
|
exact := false
|
|
if len(options) == 1 {
|
|
if *options[0].Exact {
|
|
exact = true
|
|
}
|
|
}
|
|
return f.Locator(getByLabelSelector(text, exact))
|
|
}
|
|
|
|
func (f *frameImpl) GetByPlaceholder(text interface{}, options ...FrameGetByPlaceholderOptions) Locator {
|
|
exact := false
|
|
if len(options) == 1 {
|
|
if *options[0].Exact {
|
|
exact = true
|
|
}
|
|
}
|
|
return f.Locator(getByPlaceholderSelector(text, exact))
|
|
}
|
|
|
|
func (f *frameImpl) GetByRole(role AriaRole, options ...FrameGetByRoleOptions) Locator {
|
|
if len(options) == 1 {
|
|
return f.Locator(getByRoleSelector(role, LocatorGetByRoleOptions(options[0])))
|
|
}
|
|
return f.Locator(getByRoleSelector(role))
|
|
}
|
|
|
|
func (f *frameImpl) GetByTestId(testId interface{}) Locator {
|
|
return f.Locator(getByTestIdSelector(getTestIdAttributeName(), testId))
|
|
}
|
|
|
|
func (f *frameImpl) GetByText(text interface{}, options ...FrameGetByTextOptions) Locator {
|
|
exact := false
|
|
if len(options) == 1 {
|
|
if *options[0].Exact {
|
|
exact = true
|
|
}
|
|
}
|
|
return f.Locator(getByTextSelector(text, exact))
|
|
}
|
|
|
|
func (f *frameImpl) GetByTitle(text interface{}, options ...FrameGetByTitleOptions) Locator {
|
|
exact := false
|
|
if len(options) == 1 {
|
|
if *options[0].Exact {
|
|
exact = true
|
|
}
|
|
}
|
|
return f.Locator(getByTitleSelector(text, exact))
|
|
}
|
|
|
|
func (f *frameImpl) FrameLocator(selector string) FrameLocator {
|
|
return newFrameLocator(f, selector)
|
|
}
|
|
|
|
func (f *frameImpl) highlight(selector string) error {
|
|
_, err := f.channel.Send("highlight", map[string]interface{}{
|
|
"selector": selector,
|
|
})
|
|
return err
|
|
}
|
|
|
|
func (f *frameImpl) queryCount(selector string) (int, error) {
|
|
response, err := f.channel.Send("queryCount", map[string]interface{}{
|
|
"selector": selector,
|
|
})
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return int(response.(float64)), nil
|
|
}
|