283 lines
8.1 KiB
Go
283 lines
8.1 KiB
Go
package status
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestGeminiCheckerRequestsStatsModel(t *testing.T) {
|
|
dir := t.TempDir()
|
|
fakeGemini := filepath.Join(dir, "gemini")
|
|
|
|
script := `#!/usr/bin/env sh
|
|
printf 'Gemini CLI v0.42.0\n'
|
|
printf '? for shortcuts\n'
|
|
sleep 0.1
|
|
|
|
IFS= read -r command
|
|
cmd="${command#?}"
|
|
if [ "$cmd" != "/stats model" ] && [ "$command" != "/stats model" ]; then
|
|
printf 'unexpected command: %s\n' "$command"
|
|
exit 3
|
|
fi
|
|
|
|
printf 'Auto (Gemini 3) Stats For Nerds\n'
|
|
printf '0%% used (Limit resets in 24h)\n'
|
|
printf 'Usage limit: 200\n'
|
|
printf 'Usage limits span all sessions and reset daily.\n'
|
|
|
|
IFS= read -r model_command
|
|
model_cmd="${model_command#?}"
|
|
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
|
|
printf 'unexpected command: %s\n' "$model_command"
|
|
exit 3
|
|
fi
|
|
printf 'Select Model\n'
|
|
printf 'Model usage\n'
|
|
printf 'Flash ▬▬▬ 0%% Resets: 2:15 PM (24h)\n'
|
|
printf 'Pro ▬▬▬ 2%% Resets: 2:15 PM (24h)\n'
|
|
printf '(Press Esc to close)\n'
|
|
|
|
IFS= read -r exit_command
|
|
pkill -P $$ 2>/dev/null || true
|
|
exit 0
|
|
`
|
|
|
|
if err := os.WriteFile(fakeGemini, []byte(script), 0o755); err != nil {
|
|
t.Fatalf("write fake gemini: %v", err)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
checker := NewGeminiChecker(fakeGemini)
|
|
status, err := checker.Check(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Check failed: %v", err)
|
|
}
|
|
if status.DailyLimit != "100%" {
|
|
t.Errorf("DailyLimit: got %q want %q", status.DailyLimit, "100%")
|
|
}
|
|
if status.DailyResetTime != "24h" {
|
|
t.Errorf("DailyResetTime: got %q want %q", status.DailyResetTime, "24h")
|
|
}
|
|
if status.Metadata["usage_limit"] != "200" {
|
|
t.Errorf("usage_limit: got %q want %q", status.Metadata["usage_limit"], "200")
|
|
}
|
|
if status.Metadata["used_percent"] != "0%" {
|
|
t.Errorf("used_percent: got %q want %q", status.Metadata["used_percent"], "0%")
|
|
}
|
|
if status.Metadata["daily_label"] != "Daily quota" {
|
|
t.Errorf("daily_label: got %q want %q", status.Metadata["daily_label"], "Daily quota")
|
|
}
|
|
if status.Metadata["model_usage_count"] != "2" {
|
|
t.Errorf("model_usage_count: got %q want %q", status.Metadata["model_usage_count"], "2")
|
|
}
|
|
if status.Metadata["model_usage_0_name"] != "Flash" {
|
|
t.Errorf("model_usage_0_name: got %q want %q", status.Metadata["model_usage_0_name"], "Flash")
|
|
}
|
|
if status.Metadata["model_usage_1_used_percent"] != "2%" {
|
|
t.Errorf("model_usage_1_used_percent: got %q want %q", status.Metadata["model_usage_1_used_percent"], "2%")
|
|
}
|
|
}
|
|
|
|
func TestGeminiCheckerWaitsForInputReady(t *testing.T) {
|
|
dir := t.TempDir()
|
|
fakeGemini := filepath.Join(dir, "gemini")
|
|
|
|
// Print the banner and non-input-ready workspace line first, then watch
|
|
// stdin for 0.5s. If anything is received before the prompt is rendered,
|
|
// exit 4. Only after the gap do we print the prompt and accept the real
|
|
// /stats model command.
|
|
script := `#!/usr/bin/env bash
|
|
printf 'Gemini CLI v0.42.0\n'
|
|
printf 'Tips for getting started\n'
|
|
printf 'workspace (/directory)\n'
|
|
if IFS= read -r -t 0.5 early; then
|
|
printf 'early input before prompt: %s\n' "$early"
|
|
exit 4
|
|
fi
|
|
printf '? for shortcuts\n'
|
|
|
|
IFS= read -r command
|
|
cmd="${command#?}"
|
|
if [ "$cmd" != "/stats model" ] && [ "$command" != "/stats model" ]; then
|
|
printf 'unexpected command: %s\n' "$command"
|
|
exit 3
|
|
fi
|
|
|
|
printf 'Auto (Gemini 3) Stats For Nerds\n'
|
|
printf '0%% used (Limit resets in 24h)\n'
|
|
printf 'Usage limit: 200\n'
|
|
|
|
IFS= read -r model_command
|
|
model_cmd="${model_command#?}"
|
|
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
|
|
printf 'unexpected command: %s\n' "$model_command"
|
|
exit 3
|
|
fi
|
|
printf 'Select Model\n'
|
|
printf 'Model usage\n'
|
|
printf 'Flash ▬▬▬ 0%% Resets: 2:15 PM (24h)\n'
|
|
printf '(Press Esc to close)\n'
|
|
|
|
IFS= read -r exit_command
|
|
pkill -P $$ 2>/dev/null || true
|
|
exit 0
|
|
`
|
|
|
|
if err := os.WriteFile(fakeGemini, []byte(script), 0o755); err != nil {
|
|
t.Fatalf("write fake gemini: %v", err)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
|
defer cancel()
|
|
|
|
checker := NewGeminiChecker(fakeGemini)
|
|
status, err := checker.Check(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Check failed: %v", err)
|
|
}
|
|
if status.DailyLimit != "100%" {
|
|
t.Errorf("DailyLimit: got %q want %q", status.DailyLimit, "100%")
|
|
}
|
|
if status.DailyResetTime != "24h" {
|
|
t.Errorf("DailyResetTime: got %q want %q", status.DailyResetTime, "24h")
|
|
}
|
|
if status.Metadata["usage_limit"] != "200" {
|
|
t.Errorf("usage_limit: got %q want %q", status.Metadata["usage_limit"], "200")
|
|
}
|
|
if status.Metadata["model_usage_count"] != "1" {
|
|
t.Errorf("model_usage_count: got %q want %q", status.Metadata["model_usage_count"], "1")
|
|
}
|
|
}
|
|
|
|
func TestGeminiCheckerNoAPICallsReturnsRawUnparsed(t *testing.T) {
|
|
dir := t.TempDir()
|
|
fakeGemini := filepath.Join(dir, "gemini")
|
|
|
|
script := `#!/usr/bin/env sh
|
|
printf 'Gemini CLI v0.42.0\n'
|
|
printf '? for shortcuts\n'
|
|
sleep 0.1
|
|
|
|
IFS= read -r command
|
|
cmd="${command#?}"
|
|
if [ "$cmd" != "/stats model" ] && [ "$command" != "/stats model" ]; then
|
|
printf 'unexpected command: %s\n' "$command"
|
|
exit 3
|
|
fi
|
|
|
|
printf 'Auto (Gemini 3) Stats For Nerds\n'
|
|
printf 'No API calls have been made in this session.\n'
|
|
|
|
IFS= read -r model_command
|
|
model_cmd="${model_command#?}"
|
|
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
|
|
printf 'unexpected command: %s\n' "$model_command"
|
|
exit 3
|
|
fi
|
|
printf 'Select Model\n'
|
|
printf 'Model usage\n'
|
|
printf 'Flash ▬▬▬ 0%% Resets: 2:15 PM (24h)\n'
|
|
printf '(Press Esc to close)\n'
|
|
|
|
IFS= read -r exit_command
|
|
pkill -P $$ 2>/dev/null || true
|
|
exit 0
|
|
`
|
|
|
|
if err := os.WriteFile(fakeGemini, []byte(script), 0o755); err != nil {
|
|
t.Fatalf("write fake gemini: %v", err)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
checker := NewGeminiChecker(fakeGemini)
|
|
status, err := checker.Check(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Check failed: %v", err)
|
|
}
|
|
if status.DailyLimit != "" {
|
|
t.Errorf("DailyLimit should be empty, got %q", status.DailyLimit)
|
|
}
|
|
if status.WeeklyLimit != "" {
|
|
t.Errorf("WeeklyLimit should be empty, got %q", status.WeeklyLimit)
|
|
}
|
|
if status.RawOutput == "" {
|
|
t.Error("RawOutput should not be empty")
|
|
}
|
|
if status.Metadata["model_usage_count"] != "1" {
|
|
t.Errorf("model_usage_count: got %q want %q", status.Metadata["model_usage_count"], "1")
|
|
}
|
|
}
|
|
|
|
func TestGeminiCheckerParsesScreenReaderQuotaWithNoAPICalls(t *testing.T) {
|
|
dir := t.TempDir()
|
|
fakeGemini := filepath.Join(dir, "gemini")
|
|
|
|
script := `#!/usr/bin/env sh
|
|
printf 'Gemini CLI v0.42.0\n'
|
|
printf 'workspace (/directory)\n'
|
|
printf 'Auto (Gemini 3) quota\n'
|
|
printf '0%% used\n'
|
|
printf '? for shortcuts\n'
|
|
sleep 0.1
|
|
|
|
IFS= read -r command
|
|
cmd="${command#?}"
|
|
if [ "$cmd" != "/stats model" ] && [ "$command" != "/stats model" ]; then
|
|
printf 'unexpected command: %s\n' "$command"
|
|
exit 3
|
|
fi
|
|
|
|
printf 'No API calls have been made in this session.\n'
|
|
|
|
IFS= read -r model_command
|
|
model_cmd="${model_command#?}"
|
|
if [ "$model_cmd" != "/model" ] && [ "$model_command" != "/model" ]; then
|
|
printf 'unexpected command: %s\n' "$model_command"
|
|
exit 3
|
|
fi
|
|
printf 'Select Model\n'
|
|
printf 'Model usage\n'
|
|
printf 'Flash ▬▬▬ 0%% Resets: 2:15 PM (24h)\n'
|
|
printf '(Press Esc to close)\n'
|
|
|
|
IFS= read -r exit_command
|
|
pkill -P $$ 2>/dev/null || true
|
|
exit 0
|
|
`
|
|
|
|
if err := os.WriteFile(fakeGemini, []byte(script), 0o755); err != nil {
|
|
t.Fatalf("write fake gemini: %v", err)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
checker := NewGeminiChecker(fakeGemini)
|
|
status, err := checker.Check(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Check failed: %v", err)
|
|
}
|
|
if status.DailyLimit != "100%" {
|
|
t.Errorf("DailyLimit: got %q want %q", status.DailyLimit, "100%")
|
|
}
|
|
if status.DailyResetTime != "" {
|
|
t.Errorf("DailyResetTime should be empty, got %q", status.DailyResetTime)
|
|
}
|
|
if status.Metadata["used_percent"] != "0%" {
|
|
t.Errorf("used_percent: got %q want %q", status.Metadata["used_percent"], "0%")
|
|
}
|
|
if status.Metadata["usage_limit"] != "" {
|
|
t.Errorf("usage_limit should be empty, got %q", status.Metadata["usage_limit"])
|
|
}
|
|
if status.Metadata["model_usage_count"] != "1" {
|
|
t.Errorf("model_usage_count: got %q want %q", status.Metadata["model_usage_count"], "1")
|
|
}
|
|
}
|