feat: add scanner MCP methods
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
package scanner_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"s1d3sw1ped/robinhood-agentic-mcp/client"
|
||||
"s1d3sw1ped/robinhood-agentic-mcp/internal/rhntest"
|
||||
"s1d3sw1ped/robinhood-agentic-mcp/scanner"
|
||||
)
|
||||
|
||||
func TestScanner_toolNames(t *testing.T) {
|
||||
t.Parallel()
|
||||
visible := true
|
||||
order := 1
|
||||
enumFilter := scanner.Filter{
|
||||
FilterType: "FILTER_TYPE_RSI",
|
||||
Predicate: "PREDICATE_GREATER_THAN",
|
||||
Values: []string{"70"},
|
||||
Interval: "1d",
|
||||
Length: 14,
|
||||
Plot: "close",
|
||||
}
|
||||
enumFilterWire := []map[string]any{
|
||||
{
|
||||
"filter_type": "FILTER_TYPE_RSI",
|
||||
"predicate": "PREDICATE_GREATER_THAN",
|
||||
"values": []string{"70"},
|
||||
"interval": "1d",
|
||||
"length": 14,
|
||||
"plot": "close",
|
||||
},
|
||||
}
|
||||
exprFilter := scanner.Filter{
|
||||
Predicate: "=",
|
||||
Values: []string{"True"},
|
||||
Expression: `dayVolume / volumeAvg(candleCount=30, candlePeriod="1d", session="all")`,
|
||||
DisplayTitle: "Relative volume (30D)",
|
||||
}
|
||||
exprFilterWire := []map[string]any{
|
||||
{
|
||||
"predicate": "=",
|
||||
"values": []string{"True"},
|
||||
"expression": `dayVolume / volumeAvg(candleCount=30, candlePeriod="1d", session="all")`,
|
||||
"display_title": "Relative volume (30D)",
|
||||
},
|
||||
}
|
||||
col := scanner.Column{
|
||||
DisplayName: "Put/Call volume",
|
||||
Expression: "optionsPutDayVolume / optionsCallDayVolume",
|
||||
Visible: &visible,
|
||||
Order: &order,
|
||||
}
|
||||
colWire := []map[string]any{
|
||||
{
|
||||
"display_name": "Put/Call volume",
|
||||
"expression": "optionsPutDayVolume / optionsCallDayVolume",
|
||||
"visible": true,
|
||||
"order": 1,
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
call func(*scanner.Client) error
|
||||
wantName string
|
||||
wantArgs map[string]any
|
||||
}{
|
||||
{
|
||||
name: "FilterSpecs",
|
||||
call: func(c *scanner.Client) error {
|
||||
_, err := c.FilterSpecs(context.Background(), scanner.FilterSpecsRequest{})
|
||||
return err
|
||||
},
|
||||
wantName: "get_scanner_filter_specs",
|
||||
wantArgs: map[string]any{},
|
||||
},
|
||||
{
|
||||
name: "Datapoints",
|
||||
call: func(c *scanner.Client) error {
|
||||
_, err := c.Datapoints(context.Background(), scanner.DatapointsRequest{})
|
||||
return err
|
||||
},
|
||||
wantName: "get_scanner_datapoints",
|
||||
wantArgs: map[string]any{},
|
||||
},
|
||||
{
|
||||
name: "Scans",
|
||||
call: func(c *scanner.Client) error {
|
||||
_, err := c.Scans(context.Background(), scanner.ScansRequest{})
|
||||
return err
|
||||
},
|
||||
wantName: "get_scans",
|
||||
wantArgs: map[string]any{},
|
||||
},
|
||||
{
|
||||
name: "Create",
|
||||
call: func(c *scanner.Client) error {
|
||||
_, err := c.Create(context.Background(), scanner.CreateRequest{
|
||||
ScanID: "scan-1",
|
||||
Preset: "INITIAL",
|
||||
Filters: []scanner.Filter{enumFilter},
|
||||
Columns: []scanner.Column{col},
|
||||
Title: "RSI overbought",
|
||||
})
|
||||
return err
|
||||
},
|
||||
wantName: "create_scan",
|
||||
wantArgs: map[string]any{
|
||||
"scan_id": "scan-1",
|
||||
"preset": "INITIAL",
|
||||
"filters": enumFilterWire,
|
||||
"columns": colWire,
|
||||
"title": "RSI overbought",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Preview",
|
||||
call: func(c *scanner.Client) error {
|
||||
_, err := c.Preview(context.Background(), scanner.PreviewRequest{
|
||||
Filters: []scanner.Filter{exprFilter},
|
||||
Columns: []scanner.Column{col},
|
||||
})
|
||||
return err
|
||||
},
|
||||
wantName: "preview_scan",
|
||||
wantArgs: map[string]any{
|
||||
"filters": exprFilterWire,
|
||||
"columns": colWire,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Run",
|
||||
call: func(c *scanner.Client) error {
|
||||
_, err := c.Run(context.Background(), scanner.RunRequest{ScanID: "scan-1"})
|
||||
return err
|
||||
},
|
||||
wantName: "run_scan",
|
||||
wantArgs: map[string]any{"scan_id": "scan-1"},
|
||||
},
|
||||
{
|
||||
name: "UpdateFilters",
|
||||
call: func(c *scanner.Client) error {
|
||||
_, err := c.UpdateFilters(context.Background(), scanner.UpdateFiltersRequest{
|
||||
ScanID: "scan-1",
|
||||
Filters: []scanner.Filter{enumFilter},
|
||||
})
|
||||
return err
|
||||
},
|
||||
wantName: "update_scan_filters",
|
||||
wantArgs: map[string]any{
|
||||
"scan_id": "scan-1",
|
||||
"filters": enumFilterWire,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "UpdateConfig",
|
||||
call: func(c *scanner.Client) error {
|
||||
_, err := c.UpdateConfig(context.Background(), scanner.UpdateConfigRequest{
|
||||
ScanID: "scan-1",
|
||||
SortingColumn: "Volume",
|
||||
SortingDirection: "desc",
|
||||
Columns: []scanner.Column{col},
|
||||
})
|
||||
return err
|
||||
},
|
||||
wantName: "update_scan_config",
|
||||
wantArgs: map[string]any{
|
||||
"scan_id": "scan-1",
|
||||
"sorting_column": "Volume",
|
||||
"sorting_direction": "desc",
|
||||
"columns": colWire,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
var gotName string
|
||||
var gotArgs map[string]any
|
||||
c := scanner.New(client.Func(func(ctx context.Context, name string, args map[string]any) (json.RawMessage, error) {
|
||||
gotName, gotArgs = name, args
|
||||
return json.RawMessage(`{"scans":[]}`), nil
|
||||
}))
|
||||
if err := tc.call(c); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if gotName != tc.wantName {
|
||||
t.Fatalf("%s %+v", gotName, gotArgs)
|
||||
}
|
||||
if diff := cmp.Diff(tc.wantArgs, gotArgs); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
if tc.name == "Run" {
|
||||
if gotArgs["scan_id"] != "scan-1" {
|
||||
t.Fatalf("scan_id %v", gotArgs["scan_id"])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTools(t *testing.T) {
|
||||
t.Parallel()
|
||||
want := []string{
|
||||
"create_scan",
|
||||
"get_scanner_datapoints",
|
||||
"get_scanner_filter_specs",
|
||||
"get_scans",
|
||||
"preview_scan",
|
||||
"run_scan",
|
||||
"update_scan_config",
|
||||
"update_scan_filters",
|
||||
}
|
||||
got := append([]string(nil), scanner.Tools()...)
|
||||
sort.Strings(got)
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScans_rhntest(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := rhntest.New(t)
|
||||
s.Set("get_scans", json.RawMessage(`{"scans":[]}`))
|
||||
c := scanner.New(&client.Client{URL: s.URL})
|
||||
got, err := c.Scans(context.Background(), scanner.ScansRequest{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(got.Scans) != 0 {
|
||||
t.Fatalf("%+v", got)
|
||||
}
|
||||
if s.LastName() != "get_scans" {
|
||||
t.Fatalf("%s", s.LastName())
|
||||
}
|
||||
if diff := cmp.Diff(map[string]any{}, s.LastArgs()); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user