...

Source file src/github.com/playwright-community/playwright-go/locator.go

Documentation: github.com/playwright-community/playwright-go

     1  package playwright
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"regexp"
     7  	"strconv"
     8  )
     9  
    10  type locatorImpl struct {
    11  	frame    *frameImpl
    12  	selector string
    13  	options  *LocatorLocatorOptions
    14  }
    15  
    16  func newLocator(frame *frameImpl, selector string, options ...LocatorLocatorOptions) (*locatorImpl, error) {
    17  	var option *LocatorLocatorOptions
    18  	if len(options) == 1 {
    19  		option = &options[0]
    20  		if option.HasText != nil {
    21  			switch hasText := option.HasText.(type) {
    22  			case *regexp.Regexp:
    23  				selector += fmt.Sprintf(" >> :scope:text-matches(%s)", convertRegexp(hasText))
    24  			case string:
    25  				selector += fmt.Sprintf(" >> :scope:has-text('%s')", hasText)
    26  			}
    27  		}
    28  		if option.Has != nil {
    29  			has := option.Has.(*locatorImpl)
    30  			if frame != has.frame {
    31  				return nil, errors.New("inner 'has' locator must belong to the same frame")
    32  			}
    33  			selector += " >> has=" + has.selector
    34  		}
    35  	}
    36  
    37  	return &locatorImpl{frame: frame, selector: selector, options: option}, nil
    38  }
    39  
    40  func convertRegexp(reg *regexp.Regexp) string {
    41  	matches := regexp.MustCompile(`\(\?([imsU]+)\)(.+)`).FindStringSubmatch(reg.String())
    42  
    43  	var pattern, flags string
    44  	if len(matches) == 3 {
    45  		pattern = matches[2]
    46  		flags = matches[1]
    47  	} else {
    48  		pattern = reg.String()
    49  	}
    50  	return fmt.Sprintf("'%s', '%s'", pattern, flags)
    51  }
    52  
    53  func (l *locatorImpl) AllInnerTexts() ([]string, error) {
    54  	innerTexts, err := l.frame.EvalOnSelectorAll(l.selector, "ee => ee.map(e => e.innerText)")
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	texts := innerTexts.([]interface{})
    59  	result := make([]string, len(texts))
    60  	for i := range texts {
    61  		result[i] = texts[i].(string)
    62  	}
    63  	return result, nil
    64  }
    65  
    66  func (l *locatorImpl) AllTextContents() ([]string, error) {
    67  	textContents, err := l.frame.EvalOnSelectorAll(l.selector, "ee => ee.map(e => e.textContent || '')")
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	texts := textContents.([]interface{})
    72  	result := make([]string, len(texts))
    73  	for i := range texts {
    74  		result[i] = texts[i].(string)
    75  	}
    76  	return result, nil
    77  }
    78  
    79  func (l *locatorImpl) BoundingBox(options ...LocatorBoundingBoxOptions) (*Rect, error) {
    80  	var option PageWaitForSelectorOptions
    81  	if len(options) == 1 {
    82  		option.Timeout = options[0].Timeout
    83  	}
    84  
    85  	result, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
    86  		return handle.BoundingBox()
    87  	}, option)
    88  
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	return result.(*Rect), nil
    94  }
    95  
    96  func (l *locatorImpl) Check(options ...FrameCheckOptions) error {
    97  	return l.frame.Check(l.selector, options...)
    98  }
    99  
   100  func (l *locatorImpl) Click(options ...PageClickOptions) error {
   101  	return l.frame.Click(l.selector, options...)
   102  }
   103  
   104  func (l *locatorImpl) Count() (int, error) {
   105  	return l.frame.queryCount(l.selector)
   106  }
   107  
   108  func (l *locatorImpl) Dblclick(options ...FrameDblclickOptions) error {
   109  	return l.frame.Dblclick(l.selector, options...)
   110  }
   111  
   112  func (l *locatorImpl) DispatchEvent(typ string, eventInit interface{}, options ...PageDispatchEventOptions) error {
   113  	return l.frame.DispatchEvent(l.selector, typ, eventInit, options...)
   114  }
   115  
   116  func (l *locatorImpl) DragTo(target Locator, options ...FrameDragAndDropOptions) error {
   117  	if len(options) == 1 {
   118  		options[0].Strict = Bool(true)
   119  	}
   120  	return l.frame.DragAndDrop(l.selector, target.(*locatorImpl).selector, options...)
   121  }
   122  
   123  func (l *locatorImpl) ElementHandle(options ...LocatorElementHandleOptions) (ElementHandle, error) {
   124  	option := PageWaitForSelectorOptions{
   125  		State:  WaitForSelectorStateAttached,
   126  		Strict: Bool(true),
   127  	}
   128  	if len(options) == 1 {
   129  		option.Timeout = options[0].Timeout
   130  	}
   131  	return l.frame.WaitForSelector(l.selector, option)
   132  }
   133  
   134  func (l *locatorImpl) ElementHandles() ([]ElementHandle, error) {
   135  	return l.frame.QuerySelectorAll(l.selector)
   136  }
   137  
   138  func (l *locatorImpl) Evaluate(expression string, arg interface{}, options ...LocatorEvaluateOptions) (interface{}, error) {
   139  	var option PageWaitForSelectorOptions
   140  	if len(options) == 1 {
   141  		option.Timeout = options[0].Timeout
   142  	}
   143  
   144  	return l.withElement(func(handle ElementHandle) (interface{}, error) {
   145  		return handle.Evaluate(expression, arg)
   146  	}, option)
   147  }
   148  
   149  func (l *locatorImpl) EvaluateAll(expression string, options ...interface{}) (interface{}, error) {
   150  	return l.frame.EvalOnSelectorAll(l.selector, expression, options...)
   151  }
   152  
   153  func (l *locatorImpl) EvaluateHandle(expression string, arg interface{}, options ...LocatorEvaluateHandleOptions) (interface{}, error) {
   154  	var option PageWaitForSelectorOptions
   155  	if len(options) == 1 {
   156  		option.Timeout = options[0].Timeout
   157  	}
   158  
   159  	return l.withElement(func(handle ElementHandle) (interface{}, error) {
   160  		return handle.EvaluateHandle(expression, arg)
   161  	}, option)
   162  }
   163  
   164  func (l *locatorImpl) Fill(value string, options ...FrameFillOptions) error {
   165  	if len(options) == 1 {
   166  		options[0].Strict = Bool(true)
   167  	}
   168  	return l.frame.Fill(l.selector, value, options...)
   169  }
   170  
   171  func (l *locatorImpl) First() (Locator, error) {
   172  	return newLocator(l.frame, l.selector+" >> nth=0")
   173  }
   174  
   175  func (l *locatorImpl) Focus(options ...FrameFocusOptions) error {
   176  	if len(options) == 1 {
   177  		options[0].Strict = Bool(true)
   178  	}
   179  	return l.frame.Focus(l.selector, options...)
   180  }
   181  
   182  func (l *locatorImpl) GetAttribute(name string, options ...PageGetAttributeOptions) (string, error) {
   183  	if len(options) == 1 {
   184  		options[0].Strict = Bool(true)
   185  	}
   186  	return l.frame.GetAttribute(l.selector, name, options...)
   187  }
   188  
   189  func (l *locatorImpl) Highlight() error {
   190  	return l.frame.highlight(l.selector)
   191  }
   192  
   193  func (l *locatorImpl) Hover(options ...PageHoverOptions) error {
   194  	if len(options) == 1 {
   195  		options[0].Strict = Bool(true)
   196  	}
   197  	return l.frame.Hover(l.selector, options...)
   198  }
   199  
   200  func (l *locatorImpl) InnerHTML(options ...PageInnerHTMLOptions) (string, error) {
   201  	if len(options) == 1 {
   202  		options[0].Strict = Bool(true)
   203  	}
   204  	return l.frame.InnerHTML(l.selector, options...)
   205  }
   206  
   207  func (l *locatorImpl) InnerText(options ...PageInnerTextOptions) (string, error) {
   208  	if len(options) == 1 {
   209  		options[0].Strict = Bool(true)
   210  	}
   211  	return l.frame.InnerText(l.selector, options...)
   212  }
   213  
   214  func (l *locatorImpl) InputValue(options ...FrameInputValueOptions) (string, error) {
   215  	if len(options) == 1 {
   216  		options[0].Strict = Bool(true)
   217  	}
   218  	return l.frame.InputValue(l.selector, options...)
   219  }
   220  
   221  func (l *locatorImpl) IsChecked(options ...FrameIsCheckedOptions) (bool, error) {
   222  	if len(options) == 1 {
   223  		options[0].Strict = Bool(true)
   224  	}
   225  	return l.frame.IsChecked(l.selector, options...)
   226  }
   227  
   228  func (l *locatorImpl) IsDisabled(options ...FrameIsDisabledOptions) (bool, error) {
   229  	if len(options) == 1 {
   230  		options[0].Strict = Bool(true)
   231  	}
   232  	return l.frame.IsDisabled(l.selector, options...)
   233  }
   234  
   235  func (l *locatorImpl) IsEditable(options ...FrameIsEditableOptions) (bool, error) {
   236  	if len(options) == 1 {
   237  		options[0].Strict = Bool(true)
   238  	}
   239  	return l.frame.IsEditable(l.selector, options...)
   240  }
   241  
   242  func (l *locatorImpl) IsEnabled(options ...FrameIsEnabledOptions) (bool, error) {
   243  	if len(options) == 1 {
   244  		options[0].Strict = Bool(true)
   245  	}
   246  	return l.frame.IsEnabled(l.selector, options...)
   247  }
   248  
   249  func (l *locatorImpl) IsHidden(options ...FrameIsHiddenOptions) (bool, error) {
   250  	if len(options) == 1 {
   251  		options[0].Strict = Bool(true)
   252  	}
   253  	return l.frame.IsHidden(l.selector, options...)
   254  }
   255  
   256  func (l *locatorImpl) IsVisible(options ...FrameIsVisibleOptions) (bool, error) {
   257  	if len(options) == 1 {
   258  		options[0].Strict = Bool(true)
   259  	}
   260  	return l.frame.IsVisible(l.selector, options...)
   261  }
   262  
   263  func (l *locatorImpl) Last() (Locator, error) {
   264  	return newLocator(l.frame, l.selector+" >> nth=-1")
   265  }
   266  
   267  func (l *locatorImpl) Locator(selector string) (Locator, error) {
   268  	return newLocator(l.frame, l.selector+" >> "+selector)
   269  }
   270  
   271  func (l *locatorImpl) Nth(index int) (Locator, error) {
   272  	return newLocator(l.frame, l.selector+" >> nth="+strconv.Itoa(index))
   273  }
   274  
   275  func (l *locatorImpl) Page() Page {
   276  	return l.frame.Page()
   277  }
   278  
   279  func (l *locatorImpl) Press(key string, options ...PagePressOptions) error {
   280  	if len(options) == 1 {
   281  		options[0].Strict = Bool(true)
   282  	}
   283  	return l.frame.Press(l.selector, key, options...)
   284  }
   285  
   286  func (l *locatorImpl) Screenshot(options ...LocatorScreenshotOptions) ([]byte, error) {
   287  	var option PageWaitForSelectorOptions
   288  	if len(options) == 1 {
   289  		option.Timeout = options[0].Timeout
   290  	}
   291  
   292  	result, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
   293  		var screenshotOption ElementHandleScreenshotOptions
   294  		if len(options) == 1 {
   295  			screenshotOption = ElementHandleScreenshotOptions(options[0])
   296  		}
   297  		return handle.Screenshot(screenshotOption)
   298  	}, option)
   299  
   300  	if err != nil {
   301  		return nil, err
   302  	}
   303  
   304  	return result.([]byte), nil
   305  }
   306  
   307  func (l *locatorImpl) ScrollIntoViewIfNeeded(options ...LocatorScrollIntoViewIfNeededOptions) error {
   308  	var option PageWaitForSelectorOptions
   309  	if len(options) == 1 {
   310  		option.Timeout = options[0].Timeout
   311  	}
   312  
   313  	_, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
   314  		var opt ElementHandleScrollIntoViewIfNeededOptions
   315  		if len(options) == 1 {
   316  			opt.Timeout = options[0].Timeout
   317  		}
   318  		return nil, handle.ScrollIntoViewIfNeeded(opt)
   319  	}, option)
   320  
   321  	return err
   322  }
   323  
   324  func (l *locatorImpl) SelectOption(values SelectOptionValues, options ...FrameSelectOptionOptions) ([]string, error) {
   325  	if len(options) == 1 {
   326  		options[0].Strict = Bool(true)
   327  	}
   328  	return l.frame.SelectOption(l.selector, values, options...)
   329  }
   330  
   331  func (l *locatorImpl) SelectText(options ...LocatorSelectTextOptions) error {
   332  	var option PageWaitForSelectorOptions
   333  	if len(options) == 1 {
   334  		option.Timeout = options[0].Timeout
   335  	}
   336  
   337  	_, err := l.withElement(func(handle ElementHandle) (interface{}, error) {
   338  		var opt ElementHandleSelectTextOptions
   339  		if len(options) == 1 {
   340  			opt = ElementHandleSelectTextOptions(options[0])
   341  		}
   342  		return nil, handle.SelectText(opt)
   343  	}, option)
   344  
   345  	return err
   346  }
   347  
   348  func (l *locatorImpl) SetChecked(checked bool, options ...FrameSetCheckedOptions) error {
   349  	if len(options) == 1 {
   350  		options[0].Strict = Bool(true)
   351  	}
   352  	return l.frame.SetChecked(l.selector, checked, options...)
   353  }
   354  
   355  func (l *locatorImpl) SetInputFiles(files []InputFile, options ...FrameSetInputFilesOptions) error {
   356  	if len(options) == 1 {
   357  		options[0].Strict = Bool(true)
   358  	}
   359  	return l.frame.SetInputFiles(l.selector, files, options...)
   360  }
   361  
   362  func (l *locatorImpl) Tap(options ...FrameTapOptions) error {
   363  	if len(options) == 1 {
   364  		options[0].Strict = Bool(true)
   365  	}
   366  	return l.frame.Tap(l.selector, options...)
   367  }
   368  
   369  func (l *locatorImpl) TextContent(options ...FrameTextContentOptions) (string, error) {
   370  	if len(options) == 1 {
   371  		options[0].Strict = Bool(true)
   372  	}
   373  	return l.frame.TextContent(l.selector, options...)
   374  }
   375  
   376  func (l *locatorImpl) Type(text string, options ...PageTypeOptions) error {
   377  	if len(options) == 1 {
   378  		options[0].Strict = Bool(true)
   379  	}
   380  	return l.frame.Type(l.selector, text, options...)
   381  }
   382  
   383  func (l *locatorImpl) Uncheck(options ...FrameUncheckOptions) error {
   384  	if len(options) == 1 {
   385  		options[0].Strict = Bool(true)
   386  	}
   387  	return l.frame.Uncheck(l.selector, options...)
   388  }
   389  
   390  func (l *locatorImpl) WaitFor(options ...PageWaitForSelectorOptions) error {
   391  	if len(options) == 1 {
   392  		options[0].Strict = Bool(true)
   393  	}
   394  	_, err := l.frame.WaitForSelector(l.selector, options...)
   395  	return err
   396  }
   397  
   398  func (l *locatorImpl) withElement(
   399  	callback func(handle ElementHandle) (interface{}, error),
   400  	options ...PageWaitForSelectorOptions,
   401  ) (interface{}, error) {
   402  	handle, err := l.frame.WaitForSelector(l.selector, options...)
   403  	if err != nil {
   404  		return nil, err
   405  	}
   406  
   407  	result, err := callback(handle)
   408  	if err != nil {
   409  		return nil, err
   410  	}
   411  	return result, nil
   412  }
   413  

View as plain text