accessibility
This commit is contained in:
286
client/client.go
286
client/client.go
@@ -257,8 +257,8 @@ func (c *Client) LoadURL(tabID, url string, timeout int) error {
|
||||
|
||||
// FillFormField fills a form field with a value
|
||||
// If tabID is empty, the current tab will be used
|
||||
// selectionTimeout and actionTimeout are in seconds, 0 means no timeout
|
||||
func (c *Client) FillFormField(tabID, selector, value string, selectionTimeout, actionTimeout int) error {
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) FillFormField(tabID, selector, value string, timeout int) error {
|
||||
params := map[string]string{
|
||||
"selector": selector,
|
||||
"value": value,
|
||||
@@ -269,13 +269,9 @@ func (c *Client) FillFormField(tabID, selector, value string, selectionTimeout,
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Add timeouts if specified
|
||||
if selectionTimeout > 0 {
|
||||
params["selection-timeout"] = strconv.Itoa(selectionTimeout)
|
||||
}
|
||||
|
||||
if actionTimeout > 0 {
|
||||
params["action-timeout"] = strconv.Itoa(actionTimeout)
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("fill-form", params)
|
||||
@@ -292,8 +288,8 @@ func (c *Client) FillFormField(tabID, selector, value string, selectionTimeout,
|
||||
|
||||
// UploadFile uploads a file to a file input
|
||||
// If tabID is empty, the current tab will be used
|
||||
// selectionTimeout and actionTimeout are in seconds, 0 means no timeout
|
||||
func (c *Client) UploadFile(tabID, selector, filePath string, selectionTimeout, actionTimeout int) error {
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) UploadFile(tabID, selector, filePath string, timeout int) error {
|
||||
params := map[string]string{
|
||||
"selector": selector,
|
||||
"file": filePath,
|
||||
@@ -304,13 +300,9 @@ func (c *Client) UploadFile(tabID, selector, filePath string, selectionTimeout,
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Add timeouts if specified
|
||||
if selectionTimeout > 0 {
|
||||
params["selection-timeout"] = strconv.Itoa(selectionTimeout)
|
||||
}
|
||||
|
||||
if actionTimeout > 0 {
|
||||
params["action-timeout"] = strconv.Itoa(actionTimeout)
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("upload-file", params)
|
||||
@@ -327,8 +319,8 @@ func (c *Client) UploadFile(tabID, selector, filePath string, selectionTimeout,
|
||||
|
||||
// SelectElement selects an option in a select dropdown
|
||||
// If tabID is empty, the current tab will be used
|
||||
// selectionTimeout and actionTimeout are in seconds, 0 means no timeout
|
||||
func (c *Client) SelectElement(tabID, selector, value string, selectionTimeout, actionTimeout int) error {
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) SelectElement(tabID, selector, value string, timeout int) error {
|
||||
params := map[string]string{
|
||||
"selector": selector,
|
||||
"value": value,
|
||||
@@ -339,13 +331,9 @@ func (c *Client) SelectElement(tabID, selector, value string, selectionTimeout,
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Add timeouts if specified
|
||||
if selectionTimeout > 0 {
|
||||
params["selection-timeout"] = strconv.Itoa(selectionTimeout)
|
||||
}
|
||||
|
||||
if actionTimeout > 0 {
|
||||
params["action-timeout"] = strconv.Itoa(actionTimeout)
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("select-element", params)
|
||||
@@ -362,8 +350,8 @@ func (c *Client) SelectElement(tabID, selector, value string, selectionTimeout,
|
||||
|
||||
// SubmitForm submits a form
|
||||
// If tabID is empty, the current tab will be used
|
||||
// selectionTimeout and actionTimeout are in seconds, 0 means no timeout
|
||||
func (c *Client) SubmitForm(tabID, selector string, selectionTimeout, actionTimeout int) error {
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) SubmitForm(tabID, selector string, timeout int) error {
|
||||
params := map[string]string{
|
||||
"selector": selector,
|
||||
}
|
||||
@@ -373,13 +361,9 @@ func (c *Client) SubmitForm(tabID, selector string, selectionTimeout, actionTime
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Add timeouts if specified
|
||||
if selectionTimeout > 0 {
|
||||
params["selection-timeout"] = strconv.Itoa(selectionTimeout)
|
||||
}
|
||||
|
||||
if actionTimeout > 0 {
|
||||
params["action-timeout"] = strconv.Itoa(actionTimeout)
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("submit-form", params)
|
||||
@@ -429,8 +413,8 @@ func (c *Client) GetPageSource(tabID string, timeout int) (string, error) {
|
||||
|
||||
// GetElementHTML gets the HTML of an element
|
||||
// If tabID is empty, the current tab will be used
|
||||
// selectionTimeout is in seconds, 0 means no timeout
|
||||
func (c *Client) GetElementHTML(tabID, selector string, selectionTimeout int) (string, error) {
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) GetElementHTML(tabID, selector string, timeout int) (string, error) {
|
||||
params := map[string]string{
|
||||
"selector": selector,
|
||||
}
|
||||
@@ -441,8 +425,8 @@ func (c *Client) GetElementHTML(tabID, selector string, selectionTimeout int) (s
|
||||
}
|
||||
|
||||
// Add timeout if specified
|
||||
if selectionTimeout > 0 {
|
||||
params["selection-timeout"] = strconv.Itoa(selectionTimeout)
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("get-element", params)
|
||||
@@ -644,8 +628,8 @@ func (c *Client) SwitchToMain(tabID string, timeout int) error {
|
||||
|
||||
// ClickElement clicks on an element
|
||||
// If tabID is empty, the current tab will be used
|
||||
// selectionTimeout and actionTimeout are in seconds, 0 means no timeout
|
||||
func (c *Client) ClickElement(tabID, selector string, selectionTimeout, actionTimeout int) error {
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) ClickElement(tabID, selector string, timeout int) error {
|
||||
params := map[string]string{
|
||||
"selector": selector,
|
||||
}
|
||||
@@ -655,13 +639,9 @@ func (c *Client) ClickElement(tabID, selector string, selectionTimeout, actionTi
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Add timeouts if specified
|
||||
if selectionTimeout > 0 {
|
||||
params["selection-timeout"] = strconv.Itoa(selectionTimeout)
|
||||
}
|
||||
|
||||
if actionTimeout > 0 {
|
||||
params["action-timeout"] = strconv.Itoa(actionTimeout)
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("click-element", params)
|
||||
@@ -2137,6 +2117,214 @@ func (c *Client) ScreenshotElement(tabID, selector, outputPath string, timeout i
|
||||
return nil
|
||||
}
|
||||
|
||||
// Accessibility tree data structures (matching daemon types)
|
||||
|
||||
// AXNode represents a node in the accessibility tree
|
||||
type AXNode struct {
|
||||
NodeID string `json:"nodeId"`
|
||||
Ignored bool `json:"ignored"`
|
||||
IgnoredReasons []AXProperty `json:"ignoredReasons,omitempty"`
|
||||
Role *AXValue `json:"role,omitempty"`
|
||||
ChromeRole *AXValue `json:"chromeRole,omitempty"`
|
||||
Name *AXValue `json:"name,omitempty"`
|
||||
Description *AXValue `json:"description,omitempty"`
|
||||
Value *AXValue `json:"value,omitempty"`
|
||||
Properties []AXProperty `json:"properties,omitempty"`
|
||||
ParentID string `json:"parentId,omitempty"`
|
||||
ChildIDs []string `json:"childIds,omitempty"`
|
||||
BackendDOMNodeID int `json:"backendDOMNodeId,omitempty"`
|
||||
FrameID string `json:"frameId,omitempty"`
|
||||
}
|
||||
|
||||
// AXProperty represents a property of an accessibility node
|
||||
type AXProperty struct {
|
||||
Name string `json:"name"`
|
||||
Value *AXValue `json:"value"`
|
||||
}
|
||||
|
||||
// AXValue represents a computed accessibility value
|
||||
type AXValue struct {
|
||||
Type string `json:"type"`
|
||||
Value interface{} `json:"value,omitempty"`
|
||||
RelatedNodes []AXRelatedNode `json:"relatedNodes,omitempty"`
|
||||
Sources []AXValueSource `json:"sources,omitempty"`
|
||||
}
|
||||
|
||||
// AXRelatedNode represents a related node in the accessibility tree
|
||||
type AXRelatedNode struct {
|
||||
BackendDOMNodeID int `json:"backendDOMNodeId"`
|
||||
IDRef string `json:"idref,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
}
|
||||
|
||||
// AXValueSource represents a source for a computed accessibility value
|
||||
type AXValueSource struct {
|
||||
Type string `json:"type"`
|
||||
Value *AXValue `json:"value,omitempty"`
|
||||
Attribute string `json:"attribute,omitempty"`
|
||||
AttributeValue *AXValue `json:"attributeValue,omitempty"`
|
||||
Superseded bool `json:"superseded,omitempty"`
|
||||
NativeSource string `json:"nativeSource,omitempty"`
|
||||
NativeSourceValue *AXValue `json:"nativeSourceValue,omitempty"`
|
||||
Invalid bool `json:"invalid,omitempty"`
|
||||
InvalidReason string `json:"invalidReason,omitempty"`
|
||||
}
|
||||
|
||||
// AccessibilityTreeResult represents the result of accessibility tree operations
|
||||
type AccessibilityTreeResult struct {
|
||||
Nodes []AXNode `json:"nodes"`
|
||||
}
|
||||
|
||||
// AccessibilityQueryResult represents the result of accessibility queries
|
||||
type AccessibilityQueryResult struct {
|
||||
Nodes []AXNode `json:"nodes"`
|
||||
}
|
||||
|
||||
// GetAccessibilityTree retrieves the full accessibility tree for a tab
|
||||
// If tabID is empty, the current tab will be used
|
||||
// depth limits the tree depth (optional, nil for full tree)
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) GetAccessibilityTree(tabID string, depth *int, timeout int) (*AccessibilityTreeResult, error) {
|
||||
params := map[string]string{}
|
||||
|
||||
// Only include tab ID if it's provided
|
||||
if tabID != "" {
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Add depth if specified
|
||||
if depth != nil {
|
||||
params["depth"] = strconv.Itoa(*depth)
|
||||
}
|
||||
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("get-accessibility-tree", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !resp.Success {
|
||||
return nil, fmt.Errorf("failed to get accessibility tree: %s", resp.Error)
|
||||
}
|
||||
|
||||
// Parse the response data
|
||||
var result AccessibilityTreeResult
|
||||
dataBytes, err := json.Marshal(resp.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal response data: %w", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(dataBytes, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal accessibility tree result: %w", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetPartialAccessibilityTree retrieves a partial accessibility tree for a specific element
|
||||
// If tabID is empty, the current tab will be used
|
||||
// selector is the CSS selector for the element to get the tree for
|
||||
// fetchRelatives determines whether to include ancestors, siblings, and children
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) GetPartialAccessibilityTree(tabID, selector string, fetchRelatives bool, timeout int) (*AccessibilityTreeResult, error) {
|
||||
params := map[string]string{
|
||||
"selector": selector,
|
||||
"fetch-relatives": strconv.FormatBool(fetchRelatives),
|
||||
}
|
||||
|
||||
// Only include tab ID if it's provided
|
||||
if tabID != "" {
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("get-partial-accessibility-tree", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !resp.Success {
|
||||
return nil, fmt.Errorf("failed to get partial accessibility tree: %s", resp.Error)
|
||||
}
|
||||
|
||||
// Parse the response data
|
||||
var result AccessibilityTreeResult
|
||||
dataBytes, err := json.Marshal(resp.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal response data: %w", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(dataBytes, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal accessibility tree result: %w", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// QueryAccessibilityTree queries the accessibility tree for nodes matching specific criteria
|
||||
// If tabID is empty, the current tab will be used
|
||||
// selector is optional CSS selector to limit the search scope
|
||||
// accessibleName is optional accessible name to match
|
||||
// role is optional role to match
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) QueryAccessibilityTree(tabID, selector, accessibleName, role string, timeout int) (*AccessibilityQueryResult, error) {
|
||||
params := map[string]string{}
|
||||
|
||||
// Only include tab ID if it's provided
|
||||
if tabID != "" {
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Add optional parameters
|
||||
if selector != "" {
|
||||
params["selector"] = selector
|
||||
}
|
||||
if accessibleName != "" {
|
||||
params["accessible-name"] = accessibleName
|
||||
}
|
||||
if role != "" {
|
||||
params["role"] = role
|
||||
}
|
||||
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("query-accessibility-tree", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !resp.Success {
|
||||
return nil, fmt.Errorf("failed to query accessibility tree: %s", resp.Error)
|
||||
}
|
||||
|
||||
// Parse the response data
|
||||
var result AccessibilityQueryResult
|
||||
dataBytes, err := json.Marshal(resp.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal response data: %w", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(dataBytes, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal accessibility query result: %w", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// ScreenshotEnhanced takes a screenshot with metadata
|
||||
// If tabID is empty, the current tab will be used
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
|
Reference in New Issue
Block a user