Assert journal and journal:read scopes, methods, permissions, and phrase keys in en/pl lang.yaml. Co-authored-by: Cursor <cursoragent@cursor.com>
118 lines
2.8 KiB
Go
118 lines
2.8 KiB
Go
package journal_test
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
journal "git.golem15.com/golem15/sm-journal-plugin"
|
|
"git.golem15.com/golem15/summercms/modules/pact"
|
|
"github.com/goccy/go-yaml"
|
|
)
|
|
|
|
func TestJournalTokenScopes(t *testing.T) {
|
|
p := &journal.Plugin{}
|
|
scopes := p.TokenScopes()
|
|
if len(scopes) != 2 {
|
|
t.Fatalf("TokenScopes len = %d, want 2", len(scopes))
|
|
}
|
|
byName := map[string]pact.TokenScope{}
|
|
for _, s := range scopes {
|
|
byName[s.Name] = s
|
|
}
|
|
journalScope, ok := byName["journal"]
|
|
if !ok {
|
|
t.Fatal("missing journal scope")
|
|
}
|
|
readScope, ok := byName["journal:read"]
|
|
if !ok {
|
|
t.Fatal("missing journal:read scope")
|
|
}
|
|
if len(journalScope.Permissions) != 1 || journalScope.Permissions[0] != "golem15.journal.*" {
|
|
t.Fatalf("journal permissions = %#v", journalScope.Permissions)
|
|
}
|
|
if len(readScope.Permissions) != 1 || readScope.Permissions[0] != "golem15.journal.*" {
|
|
t.Fatalf("journal:read permissions = %#v", readScope.Permissions)
|
|
}
|
|
all := []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"}
|
|
if got := journalScope.Methods; !stringSlicesEqual(got, all) {
|
|
t.Fatalf("journal methods = %#v, want %#v", got, all)
|
|
}
|
|
if got := readScope.Methods; !stringSlicesEqual(got, []string{"GET", "HEAD"}) {
|
|
t.Fatalf("journal:read methods = %#v", got)
|
|
}
|
|
|
|
keys := []string{
|
|
journalScope.Label, journalScope.Description,
|
|
readScope.Label, readScope.Description,
|
|
}
|
|
for _, lang := range []string{"en", "pl"} {
|
|
path := filepath.Join("lang", lang, "lang.yaml")
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("read %s: %v", path, err)
|
|
}
|
|
var root map[string]any
|
|
if err := yaml.Unmarshal(raw, &root); err != nil {
|
|
t.Fatalf("yaml %s: %v", path, err)
|
|
}
|
|
for _, key := range keys {
|
|
if !phraseExists(root, key) {
|
|
t.Fatalf("%s missing phrase key %s", path, key)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func stringSlicesEqual(a, b []string) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
for i := range a {
|
|
if a[i] != b[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// phraseExists resolves plugin keys like golem15.journal::lang.scopes.journal
|
|
// against the plugin lang.yaml root (scopes.journal under the file).
|
|
func phraseExists(root map[string]any, key string) bool {
|
|
const prefix = "golem15.journal::lang."
|
|
if len(key) < len(prefix) || key[:len(prefix)] != prefix {
|
|
return false
|
|
}
|
|
parts := splitDot(key[len(prefix):])
|
|
var cur any = root
|
|
for _, p := range parts {
|
|
m, ok := cur.(map[string]any)
|
|
if !ok {
|
|
return false
|
|
}
|
|
cur, ok = m[p]
|
|
if !ok {
|
|
return false
|
|
}
|
|
}
|
|
switch v := cur.(type) {
|
|
case string:
|
|
return v != ""
|
|
default:
|
|
return cur != nil
|
|
}
|
|
}
|
|
|
|
func splitDot(s string) []string {
|
|
out := []string{}
|
|
start := 0
|
|
for i := 0; i < len(s); i++ {
|
|
if s[i] == '.' {
|
|
out = append(out, s[start:i])
|
|
start = i + 1
|
|
}
|
|
}
|
|
out = append(out, s[start:])
|
|
return out
|
|
}
|