refactor(status): merge stats command into status (GH#644)
Consolidate `bd stats` and `bd status` into a unified command: - Add `stats` as alias for `status` command - Add colorized output with emoji header - Include all Statistics fields (tombstones, pinned, epics, lead time) - Add `--no-activity` flag to skip git activity parsing - Remove standalone statsCmd from ready.go (~90 lines) - Update StatusOutput to use types.Statistics directly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -251,96 +251,7 @@ var blockedCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
var statsCmd = &cobra.Command{
|
|
||||||
Use: "stats",
|
|
||||||
Short: "Show statistics",
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
// Use global jsonOutput set by PersistentPreRun (respects config.yaml + env vars)
|
|
||||||
// If daemon is running, use RPC
|
|
||||||
if daemonClient != nil {
|
|
||||||
resp, err := daemonClient.Stats()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
var stats types.Statistics
|
|
||||||
if err := json.Unmarshal(resp.Data, &stats); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if jsonOutput {
|
|
||||||
outputJSON(stats)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cyan := color.New(color.FgCyan).SprintFunc()
|
|
||||||
green := color.New(color.FgGreen).SprintFunc()
|
|
||||||
yellow := color.New(color.FgYellow).SprintFunc()
|
|
||||||
fmt.Printf("\n%s Beads Statistics:\n\n", cyan("📊"))
|
|
||||||
fmt.Printf("Total Issues: %d\n", stats.TotalIssues)
|
|
||||||
fmt.Printf("Open: %s\n", green(fmt.Sprintf("%d", stats.OpenIssues)))
|
|
||||||
fmt.Printf("In Progress: %s\n", yellow(fmt.Sprintf("%d", stats.InProgressIssues)))
|
|
||||||
fmt.Printf("Closed: %d\n", stats.ClosedIssues)
|
|
||||||
fmt.Printf("Blocked: %d\n", stats.BlockedIssues)
|
|
||||||
fmt.Printf("Ready: %s\n", green(fmt.Sprintf("%d", stats.ReadyIssues)))
|
|
||||||
if stats.TombstoneIssues > 0 {
|
|
||||||
fmt.Printf("Deleted: %d (tombstones)\n", stats.TombstoneIssues)
|
|
||||||
}
|
|
||||||
if stats.PinnedIssues > 0 {
|
|
||||||
fmt.Printf("Pinned: %d\n", stats.PinnedIssues)
|
|
||||||
}
|
|
||||||
if stats.AverageLeadTime > 0 {
|
|
||||||
fmt.Printf("Avg Lead Time: %.1f hours\n", stats.AverageLeadTime)
|
|
||||||
}
|
|
||||||
fmt.Println()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Direct mode
|
|
||||||
ctx := rootCtx
|
|
||||||
stats, err := store.GetStatistics(ctx)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
// If no issues found, check if git has issues and auto-import
|
|
||||||
if stats.TotalIssues == 0 {
|
|
||||||
if checkAndAutoImport(ctx, store) {
|
|
||||||
// Re-run the stats after import
|
|
||||||
stats, err = store.GetStatistics(ctx)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if jsonOutput {
|
|
||||||
outputJSON(stats)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cyan := color.New(color.FgCyan).SprintFunc()
|
|
||||||
green := color.New(color.FgGreen).SprintFunc()
|
|
||||||
yellow := color.New(color.FgYellow).SprintFunc()
|
|
||||||
fmt.Printf("\n%s Beads Statistics:\n\n", cyan("📊"))
|
|
||||||
fmt.Printf("Total Issues: %d\n", stats.TotalIssues)
|
|
||||||
fmt.Printf("Open: %s\n", green(fmt.Sprintf("%d", stats.OpenIssues)))
|
|
||||||
fmt.Printf("In Progress: %s\n", yellow(fmt.Sprintf("%d", stats.InProgressIssues)))
|
|
||||||
fmt.Printf("Closed: %d\n", stats.ClosedIssues)
|
|
||||||
fmt.Printf("Blocked: %d\n", stats.BlockedIssues)
|
|
||||||
fmt.Printf("Ready: %s\n", green(fmt.Sprintf("%d", stats.ReadyIssues)))
|
|
||||||
if stats.TombstoneIssues > 0 {
|
|
||||||
fmt.Printf("Deleted: %d (tombstones)\n", stats.TombstoneIssues)
|
|
||||||
}
|
|
||||||
if stats.PinnedIssues > 0 {
|
|
||||||
fmt.Printf("Pinned: %d\n", stats.PinnedIssues)
|
|
||||||
}
|
|
||||||
if stats.EpicsEligibleForClosure > 0 {
|
|
||||||
fmt.Printf("Epics Ready to Close: %s\n", green(fmt.Sprintf("%d", stats.EpicsEligibleForClosure)))
|
|
||||||
}
|
|
||||||
if stats.AverageLeadTime > 0 {
|
|
||||||
fmt.Printf("Avg Lead Time: %.1f hours\n", stats.AverageLeadTime)
|
|
||||||
}
|
|
||||||
fmt.Println()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
func init() {
|
func init() {
|
||||||
readyCmd.Flags().IntP("limit", "n", 10, "Maximum issues to show")
|
readyCmd.Flags().IntP("limit", "n", 10, "Maximum issues to show")
|
||||||
readyCmd.Flags().IntP("priority", "p", 0, "Filter by priority")
|
readyCmd.Flags().IntP("priority", "p", 0, "Filter by priority")
|
||||||
@@ -352,5 +263,4 @@ func init() {
|
|||||||
readyCmd.Flags().StringP("type", "t", "", "Filter by issue type (task, bug, feature, epic, merge-request)")
|
readyCmd.Flags().StringP("type", "t", "", "Filter by issue type (task, bug, feature, epic, merge-request)")
|
||||||
rootCmd.AddCommand(readyCmd)
|
rootCmd.AddCommand(readyCmd)
|
||||||
rootCmd.AddCommand(blockedCmd)
|
rootCmd.AddCommand(blockedCmd)
|
||||||
rootCmd.AddCommand(statsCmd)
|
|
||||||
}
|
}
|
||||||
|
|||||||
132
cmd/bd/status.go
132
cmd/bd/status.go
@@ -9,26 +9,17 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/steveyegge/beads/internal/types"
|
"github.com/steveyegge/beads/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StatusOutput represents the complete status output
|
// StatusOutput represents the complete status output
|
||||||
type StatusOutput struct {
|
type StatusOutput struct {
|
||||||
Summary *StatusSummary `json:"summary"`
|
Summary *types.Statistics `json:"summary"`
|
||||||
RecentActivity *RecentActivitySummary `json:"recent_activity,omitempty"`
|
RecentActivity *RecentActivitySummary `json:"recent_activity,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// StatusSummary represents counts by state
|
|
||||||
type StatusSummary struct {
|
|
||||||
TotalIssues int `json:"total_issues"`
|
|
||||||
OpenIssues int `json:"open_issues"`
|
|
||||||
InProgressIssues int `json:"in_progress_issues"`
|
|
||||||
BlockedIssues int `json:"blocked_issues"`
|
|
||||||
ClosedIssues int `json:"closed_issues"`
|
|
||||||
ReadyIssues int `json:"ready_issues"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecentActivitySummary represents activity from git history
|
// RecentActivitySummary represents activity from git history
|
||||||
type RecentActivitySummary struct {
|
type RecentActivitySummary struct {
|
||||||
HoursTracked int `json:"hours_tracked"`
|
HoursTracked int `json:"hours_tracked"`
|
||||||
@@ -41,12 +32,14 @@ type RecentActivitySummary struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var statusCmd = &cobra.Command{
|
var statusCmd = &cobra.Command{
|
||||||
Use: "status",
|
Use: "status",
|
||||||
Short: "Show issue database overview",
|
Aliases: []string{"stats"},
|
||||||
Long: `Show a quick snapshot of the issue database state.
|
Short: "Show issue database overview and statistics",
|
||||||
|
Long: `Show a quick snapshot of the issue database state and statistics.
|
||||||
|
|
||||||
This command provides a summary of issue counts by state (open, in_progress,
|
This command provides a summary of issue counts by state (open, in_progress,
|
||||||
blocked, closed), ready work, and recent activity over the last 24 hours from git history.
|
blocked, closed), ready work, extended statistics (tombstones, pinned issues,
|
||||||
|
average lead time), and recent activity over the last 24 hours from git history.
|
||||||
|
|
||||||
Similar to how 'git status' shows working tree state, 'bd status' gives you
|
Similar to how 'git status' shows working tree state, 'bd status' gives you
|
||||||
a quick overview of your issue database without needing multiple queries.
|
a quick overview of your issue database without needing multiple queries.
|
||||||
@@ -58,13 +51,15 @@ Use cases:
|
|||||||
- Daily standup reference
|
- Daily standup reference
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
bd status # Show summary
|
bd status # Show summary with activity
|
||||||
|
bd status --no-activity # Skip git activity (faster)
|
||||||
bd status --json # JSON format output
|
bd status --json # JSON format output
|
||||||
bd status --assigned # Show issues assigned to current user
|
bd status --assigned # Show issues assigned to current user
|
||||||
bd status --all # Show all issues (same as default)`,
|
bd stats # Alias for bd status`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
showAll, _ := cmd.Flags().GetBool("all")
|
showAll, _ := cmd.Flags().GetBool("all")
|
||||||
showAssigned, _ := cmd.Flags().GetBool("assigned")
|
showAssigned, _ := cmd.Flags().GetBool("assigned")
|
||||||
|
noActivity, _ := cmd.Flags().GetBool("no-activity")
|
||||||
jsonFormat, _ := cmd.Flags().GetBool("json")
|
jsonFormat, _ := cmd.Flags().GetBool("json")
|
||||||
|
|
||||||
// Override global jsonOutput if --json flag is set
|
// Override global jsonOutput if --json flag is set
|
||||||
@@ -108,28 +103,23 @@ Examples:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build summary
|
// Filter by assignee if requested (overrides stats with filtered counts)
|
||||||
summary := &StatusSummary{
|
if showAssigned {
|
||||||
TotalIssues: stats.TotalIssues,
|
stats = getAssignedStatistics(actor)
|
||||||
OpenIssues: stats.OpenIssues,
|
if stats == nil {
|
||||||
InProgressIssues: stats.InProgressIssues,
|
fmt.Fprintf(os.Stderr, "Error: failed to get assigned statistics\n")
|
||||||
BlockedIssues: stats.BlockedIssues,
|
os.Exit(1)
|
||||||
ClosedIssues: stats.ClosedIssues,
|
}
|
||||||
ReadyIssues: stats.ReadyIssues,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get recent activity from git history (last 24 hours)
|
// Get recent activity from git history (last 24 hours) unless --no-activity
|
||||||
var recentActivity *RecentActivitySummary
|
var recentActivity *RecentActivitySummary
|
||||||
recentActivity = getGitActivity(24)
|
if !noActivity {
|
||||||
|
recentActivity = getGitActivity(24)
|
||||||
// Filter by assignee if requested
|
|
||||||
if showAssigned {
|
|
||||||
// Get filtered statistics for assigned issues
|
|
||||||
summary = getAssignedStatus(actor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output := &StatusOutput{
|
output := &StatusOutput{
|
||||||
Summary: summary,
|
Summary: stats,
|
||||||
RecentActivity: recentActivity,
|
RecentActivity: recentActivity,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,25 +129,48 @@ Examples:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Human-readable output
|
// Human-readable colorized output
|
||||||
fmt.Println("\nIssue Database Status")
|
cyan := color.New(color.FgCyan).SprintFunc()
|
||||||
fmt.Println("=====================")
|
green := color.New(color.FgGreen).SprintFunc()
|
||||||
fmt.Printf("\nSummary:\n")
|
yellow := color.New(color.FgYellow).SprintFunc()
|
||||||
fmt.Printf(" Total Issues: %d\n", summary.TotalIssues)
|
red := color.New(color.FgRed).SprintFunc()
|
||||||
fmt.Printf(" Open: %d\n", summary.OpenIssues)
|
|
||||||
fmt.Printf(" In Progress: %d\n", summary.InProgressIssues)
|
fmt.Printf("\n%s Issue Database Status\n\n", cyan("📊"))
|
||||||
fmt.Printf(" Blocked: %d\n", summary.BlockedIssues)
|
fmt.Printf("Summary:\n")
|
||||||
fmt.Printf(" Closed: %d\n", summary.ClosedIssues)
|
fmt.Printf(" Total Issues: %d\n", stats.TotalIssues)
|
||||||
fmt.Printf(" Ready to Work: %d\n", summary.ReadyIssues)
|
fmt.Printf(" Open: %s\n", green(fmt.Sprintf("%d", stats.OpenIssues)))
|
||||||
|
fmt.Printf(" In Progress: %s\n", yellow(fmt.Sprintf("%d", stats.InProgressIssues)))
|
||||||
|
fmt.Printf(" Blocked: %s\n", red(fmt.Sprintf("%d", stats.BlockedIssues)))
|
||||||
|
fmt.Printf(" Closed: %d\n", stats.ClosedIssues)
|
||||||
|
fmt.Printf(" Ready to Work: %s\n", green(fmt.Sprintf("%d", stats.ReadyIssues)))
|
||||||
|
|
||||||
|
// Extended statistics (only show if non-zero)
|
||||||
|
hasExtended := stats.TombstoneIssues > 0 || stats.PinnedIssues > 0 ||
|
||||||
|
stats.EpicsEligibleForClosure > 0 || stats.AverageLeadTime > 0
|
||||||
|
if hasExtended {
|
||||||
|
fmt.Printf("\nExtended:\n")
|
||||||
|
if stats.TombstoneIssues > 0 {
|
||||||
|
fmt.Printf(" Deleted: %d (tombstones)\n", stats.TombstoneIssues)
|
||||||
|
}
|
||||||
|
if stats.PinnedIssues > 0 {
|
||||||
|
fmt.Printf(" Pinned: %d\n", stats.PinnedIssues)
|
||||||
|
}
|
||||||
|
if stats.EpicsEligibleForClosure > 0 {
|
||||||
|
fmt.Printf(" Epics Ready to Close: %s\n", green(fmt.Sprintf("%d", stats.EpicsEligibleForClosure)))
|
||||||
|
}
|
||||||
|
if stats.AverageLeadTime > 0 {
|
||||||
|
fmt.Printf(" Avg Lead Time: %.1f hours\n", stats.AverageLeadTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if recentActivity != nil {
|
if recentActivity != nil {
|
||||||
fmt.Printf("\nRecent Activity (last %d hours, from git history):\n", recentActivity.HoursTracked)
|
fmt.Printf("\nRecent Activity (last %d hours):\n", recentActivity.HoursTracked)
|
||||||
fmt.Printf(" Commits: %d\n", recentActivity.CommitCount)
|
fmt.Printf(" Commits: %d\n", recentActivity.CommitCount)
|
||||||
fmt.Printf(" Total Changes: %d\n", recentActivity.TotalChanges)
|
fmt.Printf(" Total Changes: %d\n", recentActivity.TotalChanges)
|
||||||
fmt.Printf(" Issues Created: %d\n", recentActivity.IssuesCreated)
|
fmt.Printf(" Issues Created: %d\n", recentActivity.IssuesCreated)
|
||||||
fmt.Printf(" Issues Closed: %d\n", recentActivity.IssuesClosed)
|
fmt.Printf(" Issues Closed: %d\n", recentActivity.IssuesClosed)
|
||||||
fmt.Printf(" Issues Reopened: %d\n", recentActivity.IssuesReopened)
|
fmt.Printf(" Issues Reopened: %d\n", recentActivity.IssuesReopened)
|
||||||
fmt.Printf(" Issues Updated: %d\n", recentActivity.IssuesUpdated)
|
fmt.Printf(" Issues Updated: %d\n", recentActivity.IssuesUpdated)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show hint for more details
|
// Show hint for more details
|
||||||
@@ -267,8 +280,8 @@ func getGitActivity(hours int) *RecentActivitySummary {
|
|||||||
return activity
|
return activity
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAssignedStatus returns status summary for issues assigned to a specific user
|
// getAssignedStatistics returns statistics for issues assigned to a specific user
|
||||||
func getAssignedStatus(assignee string) *StatusSummary {
|
func getAssignedStatistics(assignee string) *types.Statistics {
|
||||||
if store == nil {
|
if store == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -286,7 +299,7 @@ func getAssignedStatus(assignee string) *StatusSummary {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
summary := &StatusSummary{
|
stats := &types.Statistics{
|
||||||
TotalIssues: len(issues),
|
TotalIssues: len(issues),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,13 +307,13 @@ func getAssignedStatus(assignee string) *StatusSummary {
|
|||||||
for _, issue := range issues {
|
for _, issue := range issues {
|
||||||
switch issue.Status {
|
switch issue.Status {
|
||||||
case types.StatusOpen:
|
case types.StatusOpen:
|
||||||
summary.OpenIssues++
|
stats.OpenIssues++
|
||||||
case types.StatusInProgress:
|
case types.StatusInProgress:
|
||||||
summary.InProgressIssues++
|
stats.InProgressIssues++
|
||||||
case types.StatusBlocked:
|
case types.StatusBlocked:
|
||||||
summary.BlockedIssues++
|
stats.BlockedIssues++
|
||||||
case types.StatusClosed:
|
case types.StatusClosed:
|
||||||
summary.ClosedIssues++
|
stats.ClosedIssues++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,15 +323,16 @@ func getAssignedStatus(assignee string) *StatusSummary {
|
|||||||
}
|
}
|
||||||
readyIssues, err := store.GetReadyWork(ctx, readyFilter)
|
readyIssues, err := store.GetReadyWork(ctx, readyFilter)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
summary.ReadyIssues = len(readyIssues)
|
stats.ReadyIssues = len(readyIssues)
|
||||||
}
|
}
|
||||||
|
|
||||||
return summary
|
return stats
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
statusCmd.Flags().Bool("all", false, "Show all issues (default behavior)")
|
statusCmd.Flags().Bool("all", false, "Show all issues (default behavior)")
|
||||||
statusCmd.Flags().Bool("assigned", false, "Show issues assigned to current user")
|
statusCmd.Flags().Bool("assigned", false, "Show issues assigned to current user")
|
||||||
|
statusCmd.Flags().Bool("no-activity", false, "Skip git activity tracking (faster)")
|
||||||
// Note: --json flag is defined as a persistent flag in main.go, not here
|
// Note: --json flag is defined as a persistent flag in main.go, not here
|
||||||
rootCmd.AddCommand(statusCmd)
|
rootCmd.AddCommand(statusCmd)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,19 +112,9 @@ func TestStatusCommand(t *testing.T) {
|
|||||||
t.Errorf("Expected 1 closed issue, got %d", stats.ClosedIssues)
|
t.Errorf("Expected 1 closed issue, got %d", stats.ClosedIssues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test status output structures
|
// Test JSON marshaling with full Statistics
|
||||||
summary := &StatusSummary{
|
|
||||||
TotalIssues: stats.TotalIssues,
|
|
||||||
OpenIssues: stats.OpenIssues,
|
|
||||||
InProgressIssues: stats.InProgressIssues,
|
|
||||||
BlockedIssues: stats.BlockedIssues,
|
|
||||||
ClosedIssues: stats.ClosedIssues,
|
|
||||||
ReadyIssues: stats.ReadyIssues,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test JSON marshaling
|
|
||||||
output := &StatusOutput{
|
output := &StatusOutput{
|
||||||
Summary: summary,
|
Summary: stats,
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonBytes, err := json.MarshalIndent(output, "", " ")
|
jsonBytes, err := json.MarshalIndent(output, "", " ")
|
||||||
@@ -178,7 +168,7 @@ func TestGetGitActivity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAssignedStatus(t *testing.T) {
|
func TestGetAssignedStatistics(t *testing.T) {
|
||||||
// Create a temporary directory for the test database
|
// Create a temporary directory for the test database
|
||||||
tempDir := t.TempDir()
|
tempDir := t.TempDir()
|
||||||
dbPath := filepath.Join(tempDir, ".beads", "test.db")
|
dbPath := filepath.Join(tempDir, ".beads", "test.db")
|
||||||
@@ -202,7 +192,7 @@ func TestGetAssignedStatus(t *testing.T) {
|
|||||||
t.Fatalf("Failed to set issue prefix: %v", err)
|
t.Fatalf("Failed to set issue prefix: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set global store and rootCtx for getAssignedStatus
|
// Set global store and rootCtx for getAssignedStatistics
|
||||||
oldRootCtx := rootCtx
|
oldRootCtx := rootCtx
|
||||||
rootCtx = ctx
|
rootCtx = ctx
|
||||||
defer func() { rootCtx = oldRootCtx }()
|
defer func() { rootCtx = oldRootCtx }()
|
||||||
@@ -239,29 +229,29 @@ func TestGetAssignedStatus(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test getAssignedStatus for Alice
|
// Test getAssignedStatistics for Alice
|
||||||
summary := getAssignedStatus("alice")
|
stats := getAssignedStatistics("alice")
|
||||||
if summary == nil {
|
if stats == nil {
|
||||||
t.Fatal("getAssignedStatus returned nil")
|
t.Fatal("getAssignedStatistics returned nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if summary.TotalIssues != 2 {
|
if stats.TotalIssues != 2 {
|
||||||
t.Errorf("Expected 2 issues for alice, got %d", summary.TotalIssues)
|
t.Errorf("Expected 2 issues for alice, got %d", stats.TotalIssues)
|
||||||
}
|
}
|
||||||
if summary.OpenIssues != 1 {
|
if stats.OpenIssues != 1 {
|
||||||
t.Errorf("Expected 1 open issue for alice, got %d", summary.OpenIssues)
|
t.Errorf("Expected 1 open issue for alice, got %d", stats.OpenIssues)
|
||||||
}
|
}
|
||||||
if summary.InProgressIssues != 1 {
|
if stats.InProgressIssues != 1 {
|
||||||
t.Errorf("Expected 1 in-progress issue for alice, got %d", summary.InProgressIssues)
|
t.Errorf("Expected 1 in-progress issue for alice, got %d", stats.InProgressIssues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for Bob
|
// Test for Bob
|
||||||
bobSummary := getAssignedStatus("bob")
|
bobStats := getAssignedStatistics("bob")
|
||||||
if bobSummary == nil {
|
if bobStats == nil {
|
||||||
t.Fatal("getAssignedStatus returned nil for bob")
|
t.Fatal("getAssignedStatistics returned nil for bob")
|
||||||
}
|
}
|
||||||
|
|
||||||
if bobSummary.TotalIssues != 1 {
|
if bobStats.TotalIssues != 1 {
|
||||||
t.Errorf("Expected 1 issue for bob, got %d", bobSummary.TotalIssues)
|
t.Errorf("Expected 1 issue for bob, got %d", bobStats.TotalIssues)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user