test(16.3-04): pin Journal token scope registration and lang keys
Assert journal and journal:read scopes, methods, permissions, and phrase keys in en/pl lang.yaml. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
117
token_scopes_test.go
Normal file
117
token_scopes_test.go
Normal file
@@ -0,0 +1,117 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user