dt_automate/vendor/github.com/playwright-community/playwright-go/assertions.go
2025-02-19 18:30:19 +08:00

147 lines
4.0 KiB
Go

package playwright
import (
"errors"
"fmt"
"reflect"
"regexp"
"strings"
)
const assertionsDefaultTimeout = 5000 // 5s
type playwrightAssertionsImpl struct {
defaultTimeout *float64
}
// NewPlaywrightAssertions creates a new instance of PlaywrightAssertions
// - timeout: default value is 5000 (ms)
func NewPlaywrightAssertions(timeout ...float64) PlaywrightAssertions {
if len(timeout) > 0 {
return &playwrightAssertionsImpl{Float(timeout[0])}
}
return &playwrightAssertionsImpl{Float(assertionsDefaultTimeout)}
}
func (pa *playwrightAssertionsImpl) APIResponse(response APIResponse) APIResponseAssertions {
return newAPIResponseAssertions(response, false)
}
func (pa *playwrightAssertionsImpl) Locator(locator Locator) LocatorAssertions {
return newLocatorAssertions(locator, false, pa.defaultTimeout)
}
func (pa *playwrightAssertionsImpl) Page(page Page) PageAssertions {
return newPageAssertions(page, false, pa.defaultTimeout)
}
type expectedTextValue struct {
Str *string `json:"string,omitempty"`
RegexSource *string `json:"regexSource,omitempty"`
RegexFlags *string `json:"regexFlags,omitempty"`
MatchSubstring *bool `json:"matchSubstring,omitempty"`
IgnoreCase *bool `json:"ignoreCase,omitempty"`
NormalizeWhiteSpace *bool `json:"normalizeWhiteSpace,omitempty"`
}
type frameExpectOptions struct {
ExpressionArg interface{} `json:"expressionArg,omitempty"`
ExpectedText []expectedTextValue `json:"expectedText,omitempty"`
ExpectedNumber *float64 `json:"expectedNumber,omitempty"`
ExpectedValue interface{} `json:"expectedValue,omitempty"`
UseInnerText *bool `json:"useInnerText,omitempty"`
IsNot bool `json:"isNot"`
Timeout *float64 `json:"timeout"`
}
type frameExpectResult struct {
Matches bool `json:"matches"`
Received interface{} `json:"received,omitempty"`
TimedOut *bool `json:"timedOut,omitempty"`
Log []string `json:"log,omitempty"`
}
type assertionsBase struct {
actualLocator Locator
isNot bool
defaultTimeout *float64
}
func (b *assertionsBase) expect(
expression string,
options frameExpectOptions,
expected interface{},
message string,
) error {
options.IsNot = b.isNot
if options.Timeout == nil {
options.Timeout = b.defaultTimeout
}
if options.IsNot {
message = strings.ReplaceAll(message, "expected to", "expected not to")
}
result, err := b.actualLocator.(*locatorImpl).expect(expression, options)
if err != nil {
return err
}
if result.Matches == b.isNot {
actual := result.Received
log := strings.Join(result.Log, "\n")
if log != "" {
log = "\nCall log:\n" + log
}
if expected != nil {
return fmt.Errorf("%s '%v'\nActual value: %v %s", message, expected, actual, log)
}
return fmt.Errorf("%s\nActual value: %v %s", message, actual, log)
}
return nil
}
func toExpectedTextValues(
items []interface{},
matchSubstring bool,
normalizeWhiteSpace bool,
ignoreCase *bool,
) ([]expectedTextValue, error) {
var out []expectedTextValue
for _, item := range items {
switch item := item.(type) {
case string:
out = append(out, expectedTextValue{
Str: String(item),
MatchSubstring: Bool(matchSubstring),
NormalizeWhiteSpace: Bool(normalizeWhiteSpace),
IgnoreCase: ignoreCase,
})
case *regexp.Regexp:
pattern, flags := convertRegexp(item)
out = append(out, expectedTextValue{
RegexSource: String(pattern),
RegexFlags: String(flags),
MatchSubstring: Bool(matchSubstring),
NormalizeWhiteSpace: Bool(normalizeWhiteSpace),
IgnoreCase: ignoreCase,
})
default:
return nil, errors.New("value must be a string or regexp")
}
}
return out, nil
}
func convertToInterfaceList(v interface{}) []interface{} {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Slice {
return []interface{}{v}
}
list := make([]interface{}, rv.Len())
for i := 0; i < rv.Len(); i++ {
list[i] = rv.Index(i).Interface()
}
return list
}