Files
RenewCMS/test/api_catalogue_drift_test.go
T

122 lines
3.3 KiB
Go

package test
import (
"RenewCMS/api"
"RenewCMS/internal/infrastructure/config"
"net/http"
"os"
"regexp"
"sort"
"strings"
"testing"
"github.com/go-chi/chi/v5"
)
var catalogueRoutePatterns = []*regexp.Regexp{
regexp.MustCompile(`\w+\(\s*'[^']+',\s*'([A-Z]+)',\s*'([^']+)'`),
regexp.MustCompile(`row\(\s*'([A-Z]+)',\s*'([^']+)'`),
regexp.MustCompile(`method: '([A-Z]+)',\s*path: '([^']+)'`),
}
func catalogueRoutes(t *testing.T) map[string]bool {
t.Helper()
raw, err := os.ReadFile("../web/src/data/apiCatalogue.ts")
if err != nil {
t.Fatal(err)
}
routes := map[string]bool{}
for _, pattern := range catalogueRoutePatterns {
for _, m := range pattern.FindAllStringSubmatch(string(raw), -1) {
routes[m[1]+" "+strings.TrimSuffix(m[2], "/")] = true
}
}
return routes
}
func routerRoutes(t *testing.T) map[string]bool {
t.Helper()
router := api.InitBackendRoutes(&api.UseCases{}, config.Settings{})
routes := map[string]bool{}
err := chi.Walk(router, func(method, route string, _ http.Handler, _ ...func(http.Handler) http.Handler) error {
route = strings.ReplaceAll(route, "/*", "")
routes[method+" /v1"+strings.TrimSuffix(route, "/")] = true
return nil
})
if err != nil {
t.Fatal(err)
}
return routes
}
var routesNotYetInTheCatalogue = []string{
"DELETE /v1/content-type/{key}",
"DELETE /v1/content-type/{key}/entry/{id}",
"DELETE /v1/image-variants/{name}",
"DELETE /v1/media/{id}/variants/{name}",
"GET /v1/builtin-type",
"GET /v1/builtin-type/{key}",
"GET /v1/content-type",
"GET /v1/content-type/{key}",
"GET /v1/content-type/{key}/entry",
"GET /v1/content-type/{key}/entry/{id}",
"GET /v1/image-variants",
"GET /v1/image-variants/cache",
"GET /v1/media/{id}/variants",
"GET /v1/user/lookup",
"GET /v1/permission",
"PATCH /v1/image-variants/{name}",
"POST /v1/content-type",
"POST /v1/content-type/{key}/entry",
"POST /v1/image-variants",
"POST /v1/image-variants/cache/purge",
"POST /v1/image-variants/{name}/purge",
"POST /v1/media/{id}/variants",
"POST /v1/media/{id}/variants/{name}",
"PUT /v1/content-type/{key}",
"PUT /v1/content-type/{key}/entry/{id}",
"PUT /v1/image-variants/{name}",
}
func TestRouterRoutesAreInTheCatalogue(t *testing.T) {
documented := catalogueRoutes(t)
exempt := map[string]bool{}
for _, route := range routesNotYetInTheCatalogue {
exempt[route] = true
}
actual := routerRoutes(t)
var missing, stale []string
for route := range actual {
if !documented[route] && !exempt[route] {
missing = append(missing, route)
}
}
for route := range exempt {
if documented[route] || !actual[route] {
stale = append(stale, route)
}
}
sort.Strings(missing)
sort.Strings(stale)
if len(missing) > 0 {
t.Errorf("routes missing from web/src/data/apiCatalogue.ts:\n%s", strings.Join(missing, "\n"))
}
if len(stale) > 0 {
t.Errorf("routes to remove from routesNotYetInTheCatalogue:\n%s", strings.Join(stale, "\n"))
}
}
func TestCatalogueRoutesExistInTheRouter(t *testing.T) {
actual := routerRoutes(t)
var unknown []string
for route := range catalogueRoutes(t) {
if strings.Contains(route, " /v1") && !actual[route] {
unknown = append(unknown, route)
}
}
sort.Strings(unknown)
if len(unknown) > 0 {
t.Errorf("catalogue routes the router does not serve:\n%s", strings.Join(unknown, "\n"))
}
}