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