Files
2026-09-03 21:57:42 -04:00

174 lines
4.8 KiB
Go

package cli
import (
"coop-cloud-backend/cli/external"
"coop-cloud-backend/data"
"encoding/json"
"log"
"net/http"
"net/http/httptest"
"testing"
appPkg "coopcloud.tech/abra/pkg/app"
"github.com/stretchr/testify/assert"
)
func ToAny[T any](s []T) []any {
out := make([]any, len(s))
for i, v := range s {
out[i] = v
}
return out
}
// The mock call flow is
// h.cmd.Run -> h.ap.getApps -> h.ap.GetReachableServers -> h.ap.GetAppStatuses
// -(for each reachable app)> h.ap.StackName(app)
// -(reachable apps with version != "unknown" && chaos == "false")> h.rp.EnsureExists(app) and h.rp.Tags(app)
func TestListApps(t *testing.T) {
tests := []struct {
name string
// these are all of our "external" package function calls
getAppsArgs []string
getAppsOut []appPkg.App
getAppsErr error
getServsArgs []appPkg.App
getServsOut map[string]bool
getServsErr error
getStatusesArgs []interface{}
getStatusesOut map[string]map[string]string
getStatusesErr error
stackNameArgs []appPkg.App
stackNameOut []string
// these are arrays for all apps
ensureArgs []appPkg.App
ensureErrs []error
tagsArgs []appPkg.App
tagsOuts [][]string
tagsErrs []error
// these are the details for h.cmd.Run's output. Luckily the input isalways fixed
reqBody string
runOutput []byte
runErr error
// this is the final information i guess, but i need the final json thingy too
expectedBody ServerAppsResponse
expectedCode int
}{
{
name: "success one simple app",
getAppsArgs: []string{"", ""},
getAppsOut: []appPkg.App{data.App()},
getServsArgs: []appPkg.App{data.App()},
getServsOut: map[string]bool{"example.com": true},
getStatusesArgs: []interface{}{data.App(), true},
getStatusesOut: data.AppStatus(),
stackNameArgs: []appPkg.App{data.App()},
stackNameOut: []string{"nextcloud"},
ensureArgs: []appPkg.App{data.App()},
ensureErrs: []error{nil},
tagsArgs: []appPkg.App{data.App()},
tagsOuts: [][]string{{"1.2.0"}},
tagsErrs: []error{nil},
runOutput: []byte(`
{
"example.com": {
"apps": [{
"server": "example.com",
"recipe": "nextcloud",
"appName": "nextcloud.example.com",
"domain": "nextcloud.example.com",
"status": "",
"chaos": "",
"chaosVersion": "",
"version": "",
"upgrade": ""
}]
}
}
`),
expectedCode: http.StatusOK,
expectedBody: ServerAppsResponse{
"example.com": {
Apps: []AbraApp{AbraApp{
Server: "example.com",
Recipe: "nextcloud",
AppName: "nextcloud.example.com",
Domain: "nextcloud.example.com",
Status: "running",
Chaos: "false",
ChaosVersion: "unknown",
Version: "1.0.0",
Upgrade: "1.2.0",
}},
AppCount: 1,
VersionCount: 1,
UnversionedCount: 0,
LatestCount: 0,
UpgradeCount: 1,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockCmd := new(MockCommandRunner)
mockAppPkg := new(external.MockAppPackage)
mockServerPkg := new(external.MockServerPackage)
mockRecipePkg := new(external.MockRecipePackage)
mockCmd.
On("Run", "abra", "app", "ls", "-m").
Return(tt.runOutput, tt.runErr)
mockAppPkg.
On("GetApps", ToAny(tt.getAppsArgs)...).
Return(tt.getAppsOut, tt.getAppsErr)
mockServerPkg.
On("GetReachableServers", ToAny(tt.getServsArgs)...).
Return(tt.getServsOut, tt.getServsErr)
mockAppPkg.
On("GetAppStatuses", tt.getStatusesArgs...).
Return(tt.getStatusesOut, tt.getStatusesErr)
for i := range tt.stackNameArgs {
mockAppPkg.
On("StackName", []interface{}{tt.stackNameArgs[i]}...).
Return(tt.stackNameOut[i])
}
for i, ensureArg := range tt.ensureArgs {
mockRecipePkg.
On("EnsureExists", ensureArg).
Return(tt.ensureErrs[i])
log.Printf("tag output %v", tt.tagsOuts[i])
mockRecipePkg.
On("Tags", tt.tagsArgs[i]).
Return(tt.tagsOuts[i], tt.tagsErrs[i])
}
h := &abraHandler{cmd: mockCmd, ap: mockAppPkg, sp: mockServerPkg, rp: mockRecipePkg}
req := httptest.NewRequest(http.MethodPost, "/", nil)
rec := httptest.NewRecorder()
h.handleListApps(rec, req)
assert.Equal(t, tt.expectedCode, rec.Code)
var got ServerAppsResponse
if assert.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) {
assert.Equal(t, tt.expectedBody, got)
}
// may need to have "expectedRun" flags later
mockCmd.AssertExpectations(t)
mockAppPkg.AssertExpectations(t)
mockServerPkg.AssertExpectations(t)
mockRecipePkg.AssertExpectations(t)
})
}
}