1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package client_test
4
5import (
6 "strings"
7 "testing"
8 "time"
9
10 "github.com/stretchr/testify/assert"
11 "github.com/stretchr/testify/require"
12
13 "bnema.dev/ermite-api/gen/ermite"
14 "bnema.dev/ermite/internal/adapters/client"
15)
16
17func TestScopeWireNames(t *testing.T) {
18 want := map[ermite.Scope]string{
19 ermite.Scope_SCOPE_MR_REVIEW: "mr:review",
20 ermite.Scope_SCOPE_REPO_READ: "repo:read",
21 ermite.Scope_SCOPE_REPO_WRITE: "repo:write",
22 ermite.Scope_SCOPE_REPO_ADMIN: "repo:admin",
23 ermite.Scope_SCOPE_MR_WRITE: "mr:write",
24 ermite.Scope_SCOPE_MR_MERGE: "mr:merge",
25 ermite.Scope_SCOPE_CI_WRITE: "ci:write",
26 ermite.Scope_SCOPE_SECRETS_WRITE: "secrets:write",
27 ermite.Scope_SCOPE_RUNNER_REGISTER: "runner:register",
28 ermite.Scope_SCOPE_TOKEN_ADMIN: "token:admin",
29 }
30 for s, name := range want {
31 assert.Equal(t, name, client.ScopeName(s))
32 got, err := client.ParseScope(strings.ToUpper(name))
33 require.NoError(t, err)
34 assert.Equal(t, s, got)
35 }
36 assert.Len(t, client.AllScopes(), len(want), "the cli preset covers every scope of the contract")
37}
38
39func TestPresetExpansion(t *testing.T) {
40 cli, err := client.PresetScopes("cli")
41 require.NoError(t, err)
42 assert.Equal(t, client.AllScopes(), cli)
43 assert.NotContains(t, cli, ermite.Scope_SCOPE_UNSPECIFIED)
44
45 agent, err := client.PresetScopes("agent")
46 require.NoError(t, err)
47 assert.Equal(t, []ermite.Scope{ermite.Scope_SCOPE_REPO_WRITE, ermite.Scope_SCOPE_MR_WRITE}, agent)
48
49 ci, err := client.PresetScopes("CI")
50 require.NoError(t, err)
51 assert.Equal(t, []ermite.Scope{ermite.Scope_SCOPE_REPO_READ}, ci)
52
53 _, err = client.PresetScopes("root")
54 require.ErrorContains(t, err, "unknown preset")
55}
56
57func TestMergeScopes(t *testing.T) {
58 got, err := client.MergeScopes("ci", []string{"repo:write", "repo:read"})
59 require.NoError(t, err)
60 assert.Equal(t, []ermite.Scope{ermite.Scope_SCOPE_REPO_READ, ermite.Scope_SCOPE_REPO_WRITE}, got, "preset and scopes add up, sorted, no duplicates")
61
62 got, err = client.MergeScopes("", []string{"token:admin"})
63 require.NoError(t, err)
64 assert.Equal(t, []ermite.Scope{ermite.Scope_SCOPE_TOKEN_ADMIN}, got)
65
66 _, err = client.MergeScopes("", nil)
67 require.ErrorContains(t, err, "--preset")
68 _, err = client.MergeScopes("", []string{"repo:everything"})
69 require.ErrorContains(t, err, "unknown scope")
70}
71
72func TestParseExpiry(t *testing.T) {
73 now := time.Date(2026, 10, 10, 12, 0, 0, 0, time.UTC)
74 tests := []struct {
75 in string
76 want time.Time
77 }{
78 {"30d", now.Add(30 * 24 * time.Hour)},
79 {"2w", now.Add(14 * 24 * time.Hour)},
80 {"12h", now.Add(12 * time.Hour)},
81 {"1h30m", now.Add(90 * time.Minute)},
82 {"2027-01-31", time.Date(2027, 1, 31, 23, 59, 59, 0, time.UTC)},
83 {"2027-01-31T10:00:00+02:00", time.Date(2027, 1, 31, 8, 0, 0, 0, time.UTC)},
84 }
85 for _, tt := range tests {
86 got, err := client.ParseExpiry(tt.in, now)
87 require.NoError(t, err, tt.in)
88 assert.True(t, tt.want.Equal(got), "%s: %s != %s", tt.in, tt.want, got)
89 }
90 for _, in := range []string{"", "soon", "0d", "-3d", "d", "1.5d", "2026-10-09", "-1h", "99999999d"} {
91 _, err := client.ParseExpiry(in, now)
92 require.Error(t, err, in)
93 assert.Contains(t, err.Error(), "--expires")
94 }
95}