cricinfo-cli-go 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +63 -0
- package/CONTRIBUTORS.md +75 -0
- package/LICENSE +21 -0
- package/Makefile +131 -0
- package/README.md +130 -0
- package/bin/cricinfo.js +44 -0
- package/cmd/cricinfo/main.go +15 -0
- package/go.mod +10 -0
- package/go.sum +10 -0
- package/internal/app/app.go +11 -0
- package/internal/app/app_test.go +122 -0
- package/internal/buildinfo/buildinfo.go +16 -0
- package/internal/cli/analysis.go +262 -0
- package/internal/cli/analysis_test.go +175 -0
- package/internal/cli/competitions.go +154 -0
- package/internal/cli/competitions_test.go +165 -0
- package/internal/cli/leagues.go +297 -0
- package/internal/cli/leagues_test.go +194 -0
- package/internal/cli/matches.go +403 -0
- package/internal/cli/matches_test.go +413 -0
- package/internal/cli/players.go +263 -0
- package/internal/cli/players_test.go +384 -0
- package/internal/cli/root.go +141 -0
- package/internal/cli/search.go +119 -0
- package/internal/cli/teams.go +214 -0
- package/internal/cli/teams_test.go +192 -0
- package/internal/cricinfo/analysis.go +1401 -0
- package/internal/cricinfo/analysis_phase15_test.go +267 -0
- package/internal/cricinfo/client.go +471 -0
- package/internal/cricinfo/client_test.go +280 -0
- package/internal/cricinfo/cmd/fixture-refresh/main.go +145 -0
- package/internal/cricinfo/competitions.go +405 -0
- package/internal/cricinfo/competitions_phase13_test.go +234 -0
- package/internal/cricinfo/coverage_ledger.go +122 -0
- package/internal/cricinfo/coverage_ledger_test.go +253 -0
- package/internal/cricinfo/decode.go +115 -0
- package/internal/cricinfo/decode_test.go +100 -0
- package/internal/cricinfo/entity_index.go +618 -0
- package/internal/cricinfo/entity_index_test.go +175 -0
- package/internal/cricinfo/fixture_matrix.go +243 -0
- package/internal/cricinfo/fixture_matrix_test.go +49 -0
- package/internal/cricinfo/fixtures_test.go +264 -0
- package/internal/cricinfo/historical_hydration.go +1641 -0
- package/internal/cricinfo/historical_phase14_test.go +542 -0
- package/internal/cricinfo/leagues.go +1210 -0
- package/internal/cricinfo/leagues_phase12_test.go +324 -0
- package/internal/cricinfo/live_leagues_test.go +169 -0
- package/internal/cricinfo/live_matches_test.go +203 -0
- package/internal/cricinfo/live_matrix_test.go +118 -0
- package/internal/cricinfo/live_players_test.go +122 -0
- package/internal/cricinfo/live_search_test.go +86 -0
- package/internal/cricinfo/live_smoke_test.go +213 -0
- package/internal/cricinfo/live_teams_test.go +104 -0
- package/internal/cricinfo/matches.go +1508 -0
- package/internal/cricinfo/matches_phase7_test.go +207 -0
- package/internal/cricinfo/matches_phase9_test.go +253 -0
- package/internal/cricinfo/normalize_entities.go +1727 -0
- package/internal/cricinfo/normalize_leagues.go +346 -0
- package/internal/cricinfo/players.go +1332 -0
- package/internal/cricinfo/players_phase10_test.go +174 -0
- package/internal/cricinfo/players_phase11_test.go +373 -0
- package/internal/cricinfo/render_contract.go +1088 -0
- package/internal/cricinfo/render_phase4_test.go +633 -0
- package/internal/cricinfo/renderer.go +1689 -0
- package/internal/cricinfo/resolver.go +813 -0
- package/internal/cricinfo/resolver_test.go +244 -0
- package/internal/cricinfo/teams.go +603 -0
- package/internal/cricinfo/teams_phase8_test.go +231 -0
- package/internal/cricinfo/testdata/fixtures/README.md +43 -0
- package/internal/cricinfo/testdata/fixtures/aux-competition-metadata/broadcasts.json +11 -0
- package/internal/cricinfo/testdata/fixtures/aux-competition-metadata/officials.json +150 -0
- package/internal/cricinfo/testdata/fixtures/details-plays/detail-110.json +157 -0
- package/internal/cricinfo/testdata/fixtures/details-plays/detail-52545007.json +145 -0
- package/internal/cricinfo/testdata/fixtures/details-plays/detail-52559021.json +143 -0
- package/internal/cricinfo/testdata/fixtures/details-plays/plays.json +15 -0
- package/internal/cricinfo/testdata/fixtures/endpoint-matrix.tsv +19 -0
- package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/fow-1.json +12 -0
- package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/fow.json +42 -0
- package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/innings-1-2.json +38 -0
- package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/partnership-1.json +31 -0
- package/internal/cricinfo/testdata/fixtures/innings-fow-partnerships/partnerships.json +42 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/calendar-offdays.json +20 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/calendar-ondays.json +21 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/calendar.json +14 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-2025.json +13 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-group-1.json +13 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-groups.json +11 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-type-1.json +13 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/season-types.json +11 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/seasons.json +30 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/standings-item-1.json +72 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/standings-root.json +3 -0
- package/internal/cricinfo/testdata/fixtures/leagues-seasons-standings/standings.json +15 -0
- package/internal/cricinfo/testdata/fixtures/matches-competitions/competition.json +460 -0
- package/internal/cricinfo/testdata/fixtures/matches-competitions/event-1529474.json +86 -0
- package/internal/cricinfo/testdata/fixtures/matches-competitions/matchcards-1527966.json +368 -0
- package/internal/cricinfo/testdata/fixtures/matches-competitions/situation-1529474.json +10 -0
- package/internal/cricinfo/testdata/fixtures/players/athlete-1361257-statistics.json +126 -0
- package/internal/cricinfo/testdata/fixtures/players/athlete-1361257.json +113 -0
- package/internal/cricinfo/testdata/fixtures/players/roster-1361257-linescores-1-1-statistics-0.json +208 -0
- package/internal/cricinfo/testdata/fixtures/players/roster-1361257-linescores-1-2-statistics-0.json +252 -0
- package/internal/cricinfo/testdata/fixtures/players/roster-1361257-linescores.json +74 -0
- package/internal/cricinfo/testdata/fixtures/players/roster-1361257-statistics-0.json +1008 -0
- package/internal/cricinfo/testdata/fixtures/root-discovery/events.json +72 -0
- package/internal/cricinfo/testdata/fixtures/root-discovery/root.json +28 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/competitor-789643.json +40 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/leaders-789643.json +353 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/records-789643.json +91 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/roster-1147772-object.json +231 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/roster-1147772.json +235 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/roster-789643.json +322 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/scores-789643.json +19 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/statistics-789643.json +629 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/team-789643-athletes.json +7 -0
- package/internal/cricinfo/testdata/fixtures/team-competitor/team-789643.json +67 -0
- package/internal/cricinfo/testdata/golden/match-empty.golden +1 -0
- package/internal/cricinfo/testdata/golden/match-list.golden +2 -0
- package/internal/cricinfo/testdata/golden/match-partial.golden +3 -0
- package/internal/cricinfo/types.go +54 -0
- package/package.json +51 -0
- package/scripts/postinstall.js +153 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
package cli
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
"strings"
|
|
7
|
+
|
|
8
|
+
"github.com/amxv/cricinfo-cli/internal/cricinfo"
|
|
9
|
+
"github.com/spf13/cobra"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
type teamCommandService interface {
|
|
13
|
+
Close() error
|
|
14
|
+
Show(ctx context.Context, query string, opts cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error)
|
|
15
|
+
Roster(ctx context.Context, query string, opts cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error)
|
|
16
|
+
Scores(ctx context.Context, query string, opts cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error)
|
|
17
|
+
Leaders(ctx context.Context, query string, opts cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error)
|
|
18
|
+
Statistics(ctx context.Context, query string, opts cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error)
|
|
19
|
+
Records(ctx context.Context, query string, opts cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type teamRuntimeOptions struct {
|
|
23
|
+
leagueID string
|
|
24
|
+
match string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var newTeamService = func() (teamCommandService, error) {
|
|
28
|
+
return cricinfo.NewTeamService(cricinfo.TeamServiceConfig{})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func newTeamsCommand(global *globalOptions) *cobra.Command {
|
|
32
|
+
opts := &teamRuntimeOptions{}
|
|
33
|
+
|
|
34
|
+
cmd := &cobra.Command{
|
|
35
|
+
Use: "teams",
|
|
36
|
+
Short: "Team and competitor views with roster, leaders, scores, statistics, and records.",
|
|
37
|
+
Long: strings.Join([]string{
|
|
38
|
+
"Resolve teams by ID/ref/alias and drill into global team resources or match-scoped competitor resources.",
|
|
39
|
+
"Use --match to force competitor scope when a route is match-specific.",
|
|
40
|
+
"",
|
|
41
|
+
"Next steps:",
|
|
42
|
+
" cricinfo teams show <team>",
|
|
43
|
+
" cricinfo teams roster <team>",
|
|
44
|
+
" cricinfo teams roster <team> --match <match>",
|
|
45
|
+
" cricinfo teams leaders <team> --match <match>",
|
|
46
|
+
}, "\n"),
|
|
47
|
+
Args: cobra.NoArgs,
|
|
48
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
49
|
+
return cmd.Help()
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
cmd.PersistentFlags().StringVar(&opts.leagueID, "league", "", "Preferred league ID for resolver context")
|
|
54
|
+
|
|
55
|
+
showCmd := &cobra.Command{
|
|
56
|
+
Use: "show <team>",
|
|
57
|
+
Short: "Show one team summary",
|
|
58
|
+
Long: strings.Join([]string{
|
|
59
|
+
"Resolve a team by ID/ref/alias and show normalized identity fields.",
|
|
60
|
+
"",
|
|
61
|
+
"Next steps:",
|
|
62
|
+
" cricinfo teams roster <team>",
|
|
63
|
+
" cricinfo teams leaders <team> --match <match>",
|
|
64
|
+
}, "\n"),
|
|
65
|
+
Args: cobra.MinimumNArgs(1),
|
|
66
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
67
|
+
query := strings.TrimSpace(strings.Join(args, " "))
|
|
68
|
+
return runTeamCommand(cmd, global, func(ctx context.Context, service teamCommandService) (cricinfo.NormalizedResult, error) {
|
|
69
|
+
return service.Show(ctx, query, cricinfo.TeamLookupOptions{LeagueID: opts.leagueID})
|
|
70
|
+
})
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
rosterCmd := &cobra.Command{
|
|
75
|
+
Use: "roster <team>",
|
|
76
|
+
Short: "Show team roster (global athletes or match-scoped competitor roster)",
|
|
77
|
+
Long: strings.Join([]string{
|
|
78
|
+
"Without --match, roster resolves global team athletes.",
|
|
79
|
+
"With --match, roster resolves the match competitor roster and bridges entries to player refs.",
|
|
80
|
+
"",
|
|
81
|
+
"Next steps:",
|
|
82
|
+
" cricinfo teams leaders <team> --match <match>",
|
|
83
|
+
" cricinfo teams statistics <team> --match <match>",
|
|
84
|
+
}, "\n"),
|
|
85
|
+
Args: cobra.MinimumNArgs(1),
|
|
86
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
87
|
+
query := strings.TrimSpace(strings.Join(args, " "))
|
|
88
|
+
return runTeamCommand(cmd, global, func(ctx context.Context, service teamCommandService) (cricinfo.NormalizedResult, error) {
|
|
89
|
+
return service.Roster(ctx, query, cricinfo.TeamLookupOptions{LeagueID: opts.leagueID, MatchQuery: opts.match})
|
|
90
|
+
})
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
rosterCmd.Flags().StringVar(&opts.match, "match", "", "Match ID/ref/alias for match-scoped competitor roster")
|
|
94
|
+
|
|
95
|
+
scoresCmd := &cobra.Command{
|
|
96
|
+
Use: "scores <team>",
|
|
97
|
+
Short: "Show team score from a specific match competitor",
|
|
98
|
+
Long: strings.Join([]string{
|
|
99
|
+
"Resolve a team and match, then show the competitor score payload for that match.",
|
|
100
|
+
"",
|
|
101
|
+
"Next steps:",
|
|
102
|
+
" cricinfo teams leaders <team> --match <match>",
|
|
103
|
+
" cricinfo teams records <team> --match <match>",
|
|
104
|
+
}, "\n"),
|
|
105
|
+
Args: cobra.MinimumNArgs(1),
|
|
106
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
107
|
+
if strings.TrimSpace(opts.match) == "" {
|
|
108
|
+
return fmt.Errorf("--match is required")
|
|
109
|
+
}
|
|
110
|
+
query := strings.TrimSpace(strings.Join(args, " "))
|
|
111
|
+
return runTeamCommand(cmd, global, func(ctx context.Context, service teamCommandService) (cricinfo.NormalizedResult, error) {
|
|
112
|
+
return service.Scores(ctx, query, cricinfo.TeamLookupOptions{LeagueID: opts.leagueID, MatchQuery: opts.match})
|
|
113
|
+
})
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
scoresCmd.Flags().StringVar(&opts.match, "match", "", "Required: match ID/ref/alias for competitor score route")
|
|
117
|
+
|
|
118
|
+
leadersCmd := &cobra.Command{
|
|
119
|
+
Use: "leaders <team>",
|
|
120
|
+
Short: "Show team batting and bowling leaders for a specific match",
|
|
121
|
+
Long: strings.Join([]string{
|
|
122
|
+
"Resolve a team and match, then render batting and bowling leaderboards from the competitor leaders route.",
|
|
123
|
+
"",
|
|
124
|
+
"Next steps:",
|
|
125
|
+
" cricinfo teams statistics <team> --match <match>",
|
|
126
|
+
" cricinfo teams records <team> --match <match>",
|
|
127
|
+
}, "\n"),
|
|
128
|
+
Args: cobra.MinimumNArgs(1),
|
|
129
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
130
|
+
if strings.TrimSpace(opts.match) == "" {
|
|
131
|
+
return fmt.Errorf("--match is required")
|
|
132
|
+
}
|
|
133
|
+
query := strings.TrimSpace(strings.Join(args, " "))
|
|
134
|
+
return runTeamCommand(cmd, global, func(ctx context.Context, service teamCommandService) (cricinfo.NormalizedResult, error) {
|
|
135
|
+
return service.Leaders(ctx, query, cricinfo.TeamLookupOptions{LeagueID: opts.leagueID, MatchQuery: opts.match})
|
|
136
|
+
})
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
leadersCmd.Flags().StringVar(&opts.match, "match", "", "Required: match ID/ref/alias for competitor leaders route")
|
|
140
|
+
|
|
141
|
+
statisticsCmd := &cobra.Command{
|
|
142
|
+
Use: "statistics <team>",
|
|
143
|
+
Short: "Show team statistics categories for a specific match",
|
|
144
|
+
Long: strings.Join([]string{
|
|
145
|
+
"Resolve a team and match, then render competitor statistics categories.",
|
|
146
|
+
"",
|
|
147
|
+
"Next steps:",
|
|
148
|
+
" cricinfo teams records <team> --match <match>",
|
|
149
|
+
" cricinfo teams leaders <team> --match <match>",
|
|
150
|
+
}, "\n"),
|
|
151
|
+
Args: cobra.MinimumNArgs(1),
|
|
152
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
153
|
+
if strings.TrimSpace(opts.match) == "" {
|
|
154
|
+
return fmt.Errorf("--match is required")
|
|
155
|
+
}
|
|
156
|
+
query := strings.TrimSpace(strings.Join(args, " "))
|
|
157
|
+
return runTeamCommand(cmd, global, func(ctx context.Context, service teamCommandService) (cricinfo.NormalizedResult, error) {
|
|
158
|
+
return service.Statistics(ctx, query, cricinfo.TeamLookupOptions{LeagueID: opts.leagueID, MatchQuery: opts.match})
|
|
159
|
+
})
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
statisticsCmd.Flags().StringVar(&opts.match, "match", "", "Required: match ID/ref/alias for competitor statistics route")
|
|
163
|
+
|
|
164
|
+
recordsCmd := &cobra.Command{
|
|
165
|
+
Use: "records <team>",
|
|
166
|
+
Short: "Show team records categories for a specific match",
|
|
167
|
+
Long: strings.Join([]string{
|
|
168
|
+
"Resolve a team and match, then render competitor records categories.",
|
|
169
|
+
"",
|
|
170
|
+
"Next steps:",
|
|
171
|
+
" cricinfo teams scores <team> --match <match>",
|
|
172
|
+
" cricinfo teams leaders <team> --match <match>",
|
|
173
|
+
}, "\n"),
|
|
174
|
+
Args: cobra.MinimumNArgs(1),
|
|
175
|
+
RunE: func(cmd *cobra.Command, args []string) error {
|
|
176
|
+
if strings.TrimSpace(opts.match) == "" {
|
|
177
|
+
return fmt.Errorf("--match is required")
|
|
178
|
+
}
|
|
179
|
+
query := strings.TrimSpace(strings.Join(args, " "))
|
|
180
|
+
return runTeamCommand(cmd, global, func(ctx context.Context, service teamCommandService) (cricinfo.NormalizedResult, error) {
|
|
181
|
+
return service.Records(ctx, query, cricinfo.TeamLookupOptions{LeagueID: opts.leagueID, MatchQuery: opts.match})
|
|
182
|
+
})
|
|
183
|
+
},
|
|
184
|
+
}
|
|
185
|
+
recordsCmd.Flags().StringVar(&opts.match, "match", "", "Required: match ID/ref/alias for competitor records route")
|
|
186
|
+
|
|
187
|
+
cmd.AddCommand(showCmd, rosterCmd, scoresCmd, leadersCmd, statisticsCmd, recordsCmd)
|
|
188
|
+
return cmd
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
func runTeamCommand(
|
|
192
|
+
cmd *cobra.Command,
|
|
193
|
+
global *globalOptions,
|
|
194
|
+
fn func(ctx context.Context, service teamCommandService) (cricinfo.NormalizedResult, error),
|
|
195
|
+
) error {
|
|
196
|
+
service, err := newTeamService()
|
|
197
|
+
if err != nil {
|
|
198
|
+
return err
|
|
199
|
+
}
|
|
200
|
+
defer func() {
|
|
201
|
+
_ = service.Close()
|
|
202
|
+
}()
|
|
203
|
+
|
|
204
|
+
result, err := fn(cmd.Context(), service)
|
|
205
|
+
if err != nil {
|
|
206
|
+
return err
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return cricinfo.Render(cmd.OutOrStdout(), result, cricinfo.RenderOptions{
|
|
210
|
+
Format: global.format,
|
|
211
|
+
Verbose: global.verbose,
|
|
212
|
+
AllFields: global.allFields,
|
|
213
|
+
})
|
|
214
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
package cli
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"bytes"
|
|
5
|
+
"context"
|
|
6
|
+
"encoding/json"
|
|
7
|
+
"strings"
|
|
8
|
+
"testing"
|
|
9
|
+
|
|
10
|
+
"github.com/amxv/cricinfo-cli/internal/cricinfo"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
type fakeTeamService struct {
|
|
14
|
+
showResult cricinfo.NormalizedResult
|
|
15
|
+
rosterResult cricinfo.NormalizedResult
|
|
16
|
+
scoresResult cricinfo.NormalizedResult
|
|
17
|
+
leadersResult cricinfo.NormalizedResult
|
|
18
|
+
statisticsResult cricinfo.NormalizedResult
|
|
19
|
+
recordsResult cricinfo.NormalizedResult
|
|
20
|
+
|
|
21
|
+
showQueries []string
|
|
22
|
+
rosterQueries []string
|
|
23
|
+
leadersQueries []string
|
|
24
|
+
rosterOpts []cricinfo.TeamLookupOptions
|
|
25
|
+
leadersOpts []cricinfo.TeamLookupOptions
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
func (f *fakeTeamService) Close() error { return nil }
|
|
29
|
+
|
|
30
|
+
func (f *fakeTeamService) Show(_ context.Context, query string, _ cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error) {
|
|
31
|
+
f.showQueries = append(f.showQueries, query)
|
|
32
|
+
return f.showResult, nil
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func (f *fakeTeamService) Roster(_ context.Context, query string, opts cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error) {
|
|
36
|
+
f.rosterQueries = append(f.rosterQueries, query)
|
|
37
|
+
f.rosterOpts = append(f.rosterOpts, opts)
|
|
38
|
+
return f.rosterResult, nil
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func (f *fakeTeamService) Scores(context.Context, string, cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error) {
|
|
42
|
+
return f.scoresResult, nil
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
func (f *fakeTeamService) Leaders(_ context.Context, query string, opts cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error) {
|
|
46
|
+
f.leadersQueries = append(f.leadersQueries, query)
|
|
47
|
+
f.leadersOpts = append(f.leadersOpts, opts)
|
|
48
|
+
return f.leadersResult, nil
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
func (f *fakeTeamService) Statistics(context.Context, string, cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error) {
|
|
52
|
+
return f.statisticsResult, nil
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func (f *fakeTeamService) Records(context.Context, string, cricinfo.TeamLookupOptions) (cricinfo.NormalizedResult, error) {
|
|
56
|
+
return f.recordsResult, nil
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
func TestTeamsCommandsSupportIDAndAliasInputs(t *testing.T) {
|
|
60
|
+
leaders := cricinfo.TeamLeaders{
|
|
61
|
+
TeamID: "789643",
|
|
62
|
+
MatchID: "1529474",
|
|
63
|
+
Categories: []cricinfo.TeamLeaderCategory{
|
|
64
|
+
{
|
|
65
|
+
Name: "runs",
|
|
66
|
+
DisplayName: "Runs",
|
|
67
|
+
Leaders: []cricinfo.TeamLeaderEntry{
|
|
68
|
+
{AthleteID: "1108510", AthleteName: "Mohammad Ishaq", DisplayValue: "107", Balls: "141", Fours: "11", Sixes: "1"},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
Name: "wickets",
|
|
73
|
+
DisplayName: "Wickets",
|
|
74
|
+
Leaders: []cricinfo.TeamLeaderEntry{
|
|
75
|
+
{AthleteID: "1076674", AthleteName: "Amanullah Safi", DisplayValue: "7", Overs: "19.0", Runs: "81", EconomyRate: "4.26"},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
service := &fakeTeamService{
|
|
82
|
+
showResult: cricinfo.NewDataResult(cricinfo.EntityTeam, cricinfo.Team{
|
|
83
|
+
ID: "789643",
|
|
84
|
+
Name: "Boost Region",
|
|
85
|
+
ShortName: "BOOST",
|
|
86
|
+
}),
|
|
87
|
+
rosterResult: cricinfo.NewListResult(cricinfo.EntityTeamRoster, []any{
|
|
88
|
+
cricinfo.TeamRosterEntry{PlayerID: "1361257", PlayerRef: "http://core.espnuk.org/v2/sports/cricket/athletes/1361257", DisplayName: "Fazal Haq"},
|
|
89
|
+
}),
|
|
90
|
+
leadersResult: cricinfo.NewDataResult(cricinfo.EntityTeamLeaders, leaders),
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
originalFactory := newTeamService
|
|
94
|
+
newTeamService = func() (teamCommandService, error) { return service, nil }
|
|
95
|
+
defer func() {
|
|
96
|
+
newTeamService = originalFactory
|
|
97
|
+
}()
|
|
98
|
+
|
|
99
|
+
var idOut bytes.Buffer
|
|
100
|
+
var idErr bytes.Buffer
|
|
101
|
+
if err := Run([]string{"teams", "show", "789643", "--format", "json"}, &idOut, &idErr); err != nil {
|
|
102
|
+
t.Fatalf("Run teams show id error: %v", err)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
payload := decodeCLIJSONMap(t, idOut.Bytes())
|
|
106
|
+
if payload["kind"] != string(cricinfo.EntityTeam) {
|
|
107
|
+
t.Fatalf("expected kind %q, got %#v", cricinfo.EntityTeam, payload["kind"])
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
var aliasOut bytes.Buffer
|
|
111
|
+
var aliasErr bytes.Buffer
|
|
112
|
+
if err := Run([]string{"teams", "show", "Boost", "Region", "--format", "json"}, &aliasOut, &aliasErr); err != nil {
|
|
113
|
+
t.Fatalf("Run teams show alias error: %v", err)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if len(service.showQueries) != 2 {
|
|
117
|
+
t.Fatalf("expected 2 show queries, got %d", len(service.showQueries))
|
|
118
|
+
}
|
|
119
|
+
if service.showQueries[0] != "789643" {
|
|
120
|
+
t.Fatalf("expected first show query to be team ID, got %q", service.showQueries[0])
|
|
121
|
+
}
|
|
122
|
+
if service.showQueries[1] != "Boost Region" {
|
|
123
|
+
t.Fatalf("expected second show query to be alias, got %q", service.showQueries[1])
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
var rosterIDOut bytes.Buffer
|
|
127
|
+
var rosterIDErr bytes.Buffer
|
|
128
|
+
if err := Run([]string{"teams", "roster", "789643", "--match", "1529474", "--format", "json"}, &rosterIDOut, &rosterIDErr); err != nil {
|
|
129
|
+
t.Fatalf("Run teams roster id error: %v", err)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
var rosterAliasOut bytes.Buffer
|
|
133
|
+
var rosterAliasErr bytes.Buffer
|
|
134
|
+
if err := Run([]string{"teams", "roster", "Boost", "Region", "--match", "3rd Match", "--format", "json"}, &rosterAliasOut, &rosterAliasErr); err != nil {
|
|
135
|
+
t.Fatalf("Run teams roster alias error: %v", err)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if len(service.rosterQueries) != 2 {
|
|
139
|
+
t.Fatalf("expected 2 roster queries, got %d", len(service.rosterQueries))
|
|
140
|
+
}
|
|
141
|
+
if service.rosterQueries[0] != "789643" {
|
|
142
|
+
t.Fatalf("expected roster id query, got %q", service.rosterQueries[0])
|
|
143
|
+
}
|
|
144
|
+
if service.rosterQueries[1] != "Boost Region" {
|
|
145
|
+
t.Fatalf("expected roster alias query, got %q", service.rosterQueries[1])
|
|
146
|
+
}
|
|
147
|
+
if service.rosterOpts[0].MatchQuery != "1529474" || service.rosterOpts[1].MatchQuery != "3rd Match" {
|
|
148
|
+
t.Fatalf("expected roster match opts to preserve caller input, got %+v", service.rosterOpts)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
var leadersOut bytes.Buffer
|
|
152
|
+
var leadersErr bytes.Buffer
|
|
153
|
+
if err := Run([]string{"teams", "leaders", "Boost", "Region", "--match", "3rd Match", "--format", "text"}, &leadersOut, &leadersErr); err != nil {
|
|
154
|
+
t.Fatalf("Run teams leaders text error: %v", err)
|
|
155
|
+
}
|
|
156
|
+
leadersText := leadersOut.String()
|
|
157
|
+
if !strings.Contains(leadersText, "Batting Leaders") || !strings.Contains(leadersText, "Bowling Leaders") {
|
|
158
|
+
t.Fatalf("expected batting and bowling sections in leaders text output, got %q", leadersText)
|
|
159
|
+
}
|
|
160
|
+
if !strings.Contains(leadersText, "Mohammad Ishaq") || !strings.Contains(leadersText, "Amanullah Safi") {
|
|
161
|
+
t.Fatalf("expected leader names in text output, got %q", leadersText)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
func TestTeamsMatchScopedCommandsRequireMatchFlag(t *testing.T) {
|
|
166
|
+
service := &fakeTeamService{}
|
|
167
|
+
|
|
168
|
+
originalFactory := newTeamService
|
|
169
|
+
newTeamService = func() (teamCommandService, error) { return service, nil }
|
|
170
|
+
defer func() {
|
|
171
|
+
newTeamService = originalFactory
|
|
172
|
+
}()
|
|
173
|
+
|
|
174
|
+
var out bytes.Buffer
|
|
175
|
+
var errBuf bytes.Buffer
|
|
176
|
+
err := Run([]string{"teams", "scores", "789643"}, &out, &errBuf)
|
|
177
|
+
if err == nil {
|
|
178
|
+
t.Fatalf("expected error when --match is missing")
|
|
179
|
+
}
|
|
180
|
+
if !strings.Contains(err.Error(), "--match is required") {
|
|
181
|
+
t.Fatalf("expected --match required message, got %v", err)
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
func decodeCLIJSONMap(t *testing.T, data []byte) map[string]any {
|
|
186
|
+
t.Helper()
|
|
187
|
+
var payload map[string]any
|
|
188
|
+
if err := json.Unmarshal(data, &payload); err != nil {
|
|
189
|
+
t.Fatalf("decode CLI JSON: %v", err)
|
|
190
|
+
}
|
|
191
|
+
return payload
|
|
192
|
+
}
|