mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-02 14:29:44 +08:00
refactor: remove unused handlers and related files to streamline the server codebase
This commit is contained in:
@@ -117,7 +117,6 @@ func (s *MCPServer4XTDriver) registerTools() {
|
||||
s.registerTool(&ToolClosePopups{})
|
||||
|
||||
// PC/Web Tools
|
||||
s.registerTool(&ToolWebLoginNoneUI{})
|
||||
s.registerTool(&ToolSecondaryClick{})
|
||||
s.registerTool(&ToolHoverBySelector{})
|
||||
s.registerTool(&ToolTapBySelector{})
|
||||
|
||||
@@ -3,7 +3,6 @@ package option
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand/v2"
|
||||
"reflect"
|
||||
"strings"
|
||||
@@ -563,188 +562,6 @@ func WithOutputSchema(schema interface{}) ActionOption {
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP API direct usage methods
|
||||
|
||||
// ValidateForHTTPAPI validates the request for HTTP API usage
|
||||
func (o *ActionOptions) ValidateForHTTPAPI(actionType ActionName) error {
|
||||
// Basic validation - Platform and Serial are set from URL, so skip here
|
||||
// They will be validated by setRequestContextFromURL
|
||||
|
||||
// Action-specific validation using a more efficient approach
|
||||
return o.validateActionSpecificFields(actionType)
|
||||
}
|
||||
|
||||
// validateActionSpecificFields performs action-specific field validation
|
||||
func (o *ActionOptions) validateActionSpecificFields(actionType ActionName) error {
|
||||
// Define validation rules for each action type using ActionMethod constants
|
||||
validationRules := map[ActionName]func() error{
|
||||
ACTION_Tap: func() error {
|
||||
return o.requireFields("x and y coordinates", o.X != 0 && o.Y != 0)
|
||||
},
|
||||
ACTION_TapXY: func() error {
|
||||
return o.requireFields("x and y coordinates", o.X != 0 && o.Y != 0)
|
||||
},
|
||||
ACTION_TapAbsXY: func() error {
|
||||
return o.requireFields("x and y coordinates", o.X != 0 && o.Y != 0)
|
||||
},
|
||||
ACTION_DoubleTap: func() error {
|
||||
return o.requireFields("x and y coordinates", o.X != 0 && o.Y != 0)
|
||||
},
|
||||
ACTION_DoubleTapXY: func() error {
|
||||
return o.requireFields("x and y coordinates", o.X != 0 && o.Y != 0)
|
||||
},
|
||||
ACTION_RightClick: func() error {
|
||||
return o.requireFields("x and y coordinates", o.X != 0 && o.Y != 0)
|
||||
},
|
||||
ACTION_SecondaryClick: func() error {
|
||||
return o.requireFields("x and y coordinates", o.X != 0 && o.Y != 0)
|
||||
},
|
||||
ACTION_Hover: func() error {
|
||||
return o.requireFields("x and y coordinates", o.X != 0 && o.Y != 0)
|
||||
},
|
||||
ACTION_Drag: func() error {
|
||||
return o.requireFields("fromX, fromY, toX, toY coordinates",
|
||||
o.FromX != 0 && o.FromY != 0 && o.ToX != 0 && o.ToY != 0)
|
||||
},
|
||||
ACTION_SwipeCoordinate: func() error {
|
||||
return o.requireFields("fromX, fromY, toX, toY coordinates",
|
||||
o.FromX != 0 && o.FromY != 0 && o.ToX != 0 && o.ToY != 0)
|
||||
},
|
||||
ACTION_Swipe: func() error {
|
||||
return o.requireFields("direction", o.Direction != nil && o.Direction != "")
|
||||
},
|
||||
ACTION_SwipeDirection: func() error {
|
||||
return o.requireFields("direction", o.Direction != nil && o.Direction != "")
|
||||
},
|
||||
ACTION_Input: func() error {
|
||||
return o.requireFields("text", o.Text != "")
|
||||
},
|
||||
ACTION_Delete: func() error {
|
||||
// Count is optional, will use default if not provided
|
||||
return nil
|
||||
},
|
||||
ACTION_Backspace: func() error {
|
||||
// Count is optional, will use default if not provided
|
||||
return nil
|
||||
},
|
||||
ACTION_KeyCode: func() error {
|
||||
return o.requireFields("keycode", o.Keycode != 0)
|
||||
},
|
||||
ACTION_Scroll: func() error {
|
||||
return o.requireFields("delta", o.Delta != 0)
|
||||
},
|
||||
ACTION_AppInfo: func() error {
|
||||
return o.requireFields("packageName", o.PackageName != "")
|
||||
},
|
||||
ACTION_AppClear: func() error {
|
||||
return o.requireFields("packageName", o.PackageName != "")
|
||||
},
|
||||
ACTION_AppLaunch: func() error {
|
||||
return o.requireFields("packageName", o.PackageName != "")
|
||||
},
|
||||
ACTION_AppTerminate: func() error {
|
||||
return o.requireFields("packageName", o.PackageName != "")
|
||||
},
|
||||
ACTION_AppUninstall: func() error {
|
||||
return o.requireFields("packageName", o.PackageName != "")
|
||||
},
|
||||
ACTION_AppInstall: func() error {
|
||||
return o.requireFields("appUrl", o.AppUrl != "")
|
||||
},
|
||||
ACTION_GetForegroundApp: func() error {
|
||||
return nil
|
||||
},
|
||||
ACTION_TapByOCR: func() error {
|
||||
return o.requireFields("text", o.Text != "")
|
||||
},
|
||||
ACTION_SwipeToTapText: func() error {
|
||||
return o.requireFields("text", o.Text != "")
|
||||
},
|
||||
ACTION_TapByCV: func() error {
|
||||
return o.requireFields("imagePath", o.ImagePath != "")
|
||||
},
|
||||
ACTION_SwipeToTapApp: func() error {
|
||||
return o.requireFields("appName", o.AppName != "")
|
||||
},
|
||||
ACTION_SwipeToTapTexts: func() error {
|
||||
return o.requireFields("texts array", len(o.Texts) > 0)
|
||||
},
|
||||
ACTION_TapBySelector: func() error {
|
||||
return o.requireFields("selector", o.Selector != "")
|
||||
},
|
||||
ACTION_HoverBySelector: func() error {
|
||||
return o.requireFields("selector", o.Selector != "")
|
||||
},
|
||||
ACTION_SecondaryClickBySelector: func() error {
|
||||
return o.requireFields("selector", o.Selector != "")
|
||||
},
|
||||
ACTION_WebCloseTab: func() error {
|
||||
return o.requireFields("tabIndex", o.TabIndex != 0)
|
||||
},
|
||||
ACTION_WebLoginNoneUI: func() error {
|
||||
if o.PackageName == "" || o.PhoneNumber == "" || o.Captcha == "" || o.Password == "" {
|
||||
return fmt.Errorf("packageName, phoneNumber, captcha, and password are required for web_login_none_ui action")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
ACTION_SetIme: func() error {
|
||||
return o.requireFields("ime", o.Ime != "")
|
||||
},
|
||||
ACTION_GetSource: func() error {
|
||||
return o.requireFields("packageName", o.PackageName != "")
|
||||
},
|
||||
ACTION_SleepMS: func() error {
|
||||
return o.requireFields("milliseconds", o.Milliseconds != 0)
|
||||
},
|
||||
ACTION_SleepRandom: func() error {
|
||||
return o.requireFields("params array", len(o.Params) > 0)
|
||||
},
|
||||
ACTION_AIAction: func() error {
|
||||
return o.requireFields("prompt", o.Prompt != "")
|
||||
},
|
||||
ACTION_StartToGoal: func() error {
|
||||
return o.requireFields("prompt", o.Prompt != "")
|
||||
},
|
||||
ACTION_Query: func() error {
|
||||
return o.requireFields("prompt", o.Prompt != "")
|
||||
},
|
||||
ACTION_Finished: func() error {
|
||||
return o.requireFields("content", o.Content != "")
|
||||
},
|
||||
ACTION_Upload: func() error {
|
||||
if o.X == 0 || o.Y == 0 || o.FileUrl == "" {
|
||||
return fmt.Errorf("x, y coordinates and fileUrl are required for upload action")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
ACTION_PushMedia: func() error {
|
||||
if o.ImageUrl == "" && o.VideoUrl == "" {
|
||||
return fmt.Errorf("either imageUrl or videoUrl is required for push_media action")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
ACTION_CreateBrowser: func() error {
|
||||
return o.requireFields("timeout", o.Timeout != 0)
|
||||
},
|
||||
}
|
||||
|
||||
// Execute validation rule for the action type
|
||||
if validator, exists := validationRules[actionType]; exists {
|
||||
return validator()
|
||||
}
|
||||
|
||||
// No specific validation needed for this action type
|
||||
return nil
|
||||
}
|
||||
|
||||
// requireFields is a helper function to generate consistent error messages
|
||||
func (o *ActionOptions) requireFields(fieldDesc string, condition bool) error {
|
||||
if !condition {
|
||||
return fmt.Errorf("%s is required for this action", fieldDesc)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMCPOptions generates MCP tool options for specific action types
|
||||
func (o *ActionOptions) GetMCPOptions(actionType ActionName) []mcp.ToolOption {
|
||||
// Define field mappings for different action types
|
||||
|
||||
@@ -66,7 +66,7 @@ const (
|
||||
// It helps you to handle an arbitrary element as accept button in accept alert command.
|
||||
// The selector should be a valid class chain expression, where the search root is the alert element itself.
|
||||
// The default button location algorithm is used if the provided selector is wrong or does not match any element.
|
||||
// e.g. **/XCUIElementTypeButton[`label CONTAINS[c] ‘accept’`]
|
||||
// e.g. **/XCUIElementTypeButton[`label CONTAINS[c] 'accept'`]
|
||||
acceptAlertButtonSelector = "**/XCUIElementTypeButton[`label IN {'允许','好','仅在使用应用期间','稍后再说'}`]"
|
||||
dismissAlertButtonSelector = "**/XCUIElementTypeButton[`label IN {'不允许','暂不'}`]"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user