Files
gochat/channels/shangwutong/internal/command/root_test.go
T

128 lines
4.1 KiB
Go

package command
import (
"bytes"
"context"
"errors"
"io"
"net/http"
"net/http/httptest"
"path/filepath"
"strings"
"testing"
"time"
"github.com/gochat/gochat/channels/shangwutong/internal/store"
"github.com/sirupsen/logrus"
)
func TestRootCommandExposesOnlyPlannedOperations(t *testing.T) {
root := NewRootCommand()
want := map[string]bool{"serve": false, "migrate": false, "reconcile": false, "backup": false, "doctor": false}
for _, command := range root.Commands() {
if _, ok := want[command.Name()]; ok {
want[command.Name()] = true
}
}
for name, found := range want {
if !found {
t.Fatalf("missing command %s", name)
}
}
}
func TestBackupRequiresOutput(t *testing.T) {
root := NewRootCommand()
root.SetArgs([]string{"backup"})
root.SetOut(&bytes.Buffer{})
if err := root.Execute(); err == nil || !strings.Contains(err.Error(), "--output is required") {
t.Fatalf("error = %v", err)
}
}
func TestMigrateRejectsUnknownAction(t *testing.T) {
t.Setenv("SWT_CONNECTOR_DB_PATH", filepath.Join(t.TempDir(), "connector.db"))
root := NewRootCommand()
root.SetArgs([]string{"migrate", "down"})
if err := root.Execute(); err == nil || !strings.Contains(err.Error(), "unsupported migration action") {
t.Fatalf("error = %v", err)
}
}
func TestLocalAdminURLUsesLoopbackForWildcardListen(t *testing.T) {
got, err := localAdminURL(":9200")
if err != nil || got != "http://127.0.0.1:9200" {
t.Fatalf("URL = %q, %v", got, err)
}
}
func TestStartupReconcileRetriesUntilFirstCompleteSnapshot(t *testing.T) {
attempts := 0
logger := logrus.New()
logger.SetOutput(io.Discard)
reconcileUntilSuccessful(context.Background(), func(context.Context) error {
attempts++
if attempts == 1 {
return errors.New("GoChat unavailable")
}
return nil
}, logrus.NewEntry(logger), time.Millisecond)
if attempts != 2 {
t.Fatalf("attempts = %d", attempts)
}
}
func TestOperationalCommands(t *testing.T) {
directory := t.TempDir()
databasePath, backupPath := filepath.Join(directory, "connector.db"), filepath.Join(directory, "backup.db")
t.Setenv("SWT_CONNECTOR_DB_PATH", databasePath)
for _, args := range [][]string{{"migrate", "up"}, {"migrate", "status"}, {"backup", "--output", backupPath}} {
root, output := NewRootCommand(), &bytes.Buffer{}
root.SetArgs(args)
root.SetOut(output)
if err := root.Execute(); err != nil {
t.Fatalf("%v: %v", args, err)
}
if output.Len() == 0 {
t.Fatalf("%v produced no output", args)
}
}
if version, err := store.InspectDatabase(context.Background(), backupPath); err != nil || version != 8 {
t.Fatalf("backup version = %d, %v", version, err)
}
goChat := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/api/v1/connector/shangwutong/inboxes" || request.Header.Get("Authorization") != "Bearer service-token" {
http.Error(response, "unexpected request", http.StatusBadRequest)
return
}
response.Header().Set("Content-Type", "application/json")
_, _ = io.WriteString(response, `{"data":[],"next_cursor":""}`)
}))
defer goChat.Close()
t.Setenv("GOCHAT_BASE_URL", goChat.URL)
t.Setenv("GOCHAT_CONNECTOR_SERVICE_TOKEN", "service-token")
root, output := NewRootCommand(), &bytes.Buffer{}
root.SetArgs([]string{"doctor"})
root.SetOut(output)
if err := root.Execute(); err != nil || !strings.Contains(output.String(), "inboxes=0") {
t.Fatalf("doctor output=%q err=%v", output.String(), err)
}
reconcile := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
if request.Method != http.MethodPost || request.URL.Path != "/internal/reconcile" {
http.Error(response, "unexpected request", http.StatusBadRequest)
return
}
response.WriteHeader(http.StatusAccepted)
}))
defer reconcile.Close()
t.Setenv("SWT_CONNECTOR_LISTEN", strings.TrimPrefix(reconcile.URL, "http://"))
root, output = NewRootCommand(), &bytes.Buffer{}
root.SetArgs([]string{"reconcile"})
root.SetOut(output)
if err := root.Execute(); err != nil || !strings.Contains(output.String(), "reconcile accepted") {
t.Fatalf("reconcile output=%q err=%v", output.String(), err)
}
}