v2.31.0-dev8 ec8c5b9

handler_test.go RawHistoryFolder

1package preview
2
3import (
4	"context"
5	"sync"
6	"testing"
7	"time"
8
9	"github.com/stretchr/testify/assert"
10	"github.com/stretchr/testify/require"
11
12	"github.com/bnema/gordon/internal/domain"
13)
14
15type captureStore struct {
16	mu       sync.Mutex
17	previews []domain.PreviewRoute
18	history  [][]domain.PreviewRoute
19}
20
21func (s *captureStore) Load(_ context.Context) ([]domain.PreviewRoute, error) {
22	s.mu.Lock()
23	defer s.mu.Unlock()
24	cp := make([]domain.PreviewRoute, len(s.previews))
25	copy(cp, s.previews)
26	return cp, nil
27}
28
29func (s *captureStore) Save(_ context.Context, previews []domain.PreviewRoute) error {
30	s.mu.Lock()
31	defer s.mu.Unlock()
32	s.previews = make([]domain.PreviewRoute, len(previews))
33	copy(s.previews, previews)
34	snapshot := make([]domain.PreviewRoute, len(previews))
35	copy(snapshot, previews)
36	s.history = append(s.history, snapshot)
37	return nil
38}
39
40func (s *captureStore) saves() [][]domain.PreviewRoute {
41	s.mu.Lock()
42	defer s.mu.Unlock()
43	cp := make([][]domain.PreviewRoute, len(s.history))
44	for i := range s.history {
45		cp[i] = make([]domain.PreviewRoute, len(s.history[i]))
46		copy(cp[i], s.history[i])
47	}
48	return cp
49}
50
51type fakeAutoConfigProvider struct {
52	previewConfig  domain.PreviewConfig
53	routesByImage  map[string][]domain.Route
54	allowedDomains []string
55}
56
57func (f *fakeAutoConfigProvider) IsAutoEnabled() bool                    { return false }
58func (f *fakeAutoConfigProvider) IsPreviewEnabled() bool                 { return true }
59func (f *fakeAutoConfigProvider) GetPreviewTagPatterns() []string        { return f.previewConfig.TagPatterns }
60func (f *fakeAutoConfigProvider) GetPreviewConfig() domain.PreviewConfig { return f.previewConfig }
61func (f *fakeAutoConfigProvider) GetAllowedDomains() []string            { return f.allowedDomains }
62func (f *fakeAutoConfigProvider) FindRoutesByImage(_ context.Context, imageName string) []domain.Route {
63	return f.routesByImage[imageName]
64}
65
66func TestAutoPreviewHandler_CanHandle(t *testing.T) {
67	h := &AutoPreviewHandler{}
68	assert.True(t, h.CanHandle(domain.EventImagePushed))
69	assert.False(t, h.CanHandle(domain.EventConfigReload))
70}
71
72func TestResolveBaseRoutes_ReturnsAllEligibleBases(t *testing.T) {
73	routes := []domain.Route{
74		{Domain: "app-preview-old.example.com", Image: "myapp", HTTPS: true},
75		{Domain: "app.example.com", Image: "myapp", HTTPS: true},
76		{Domain: "alias.example.com", Image: "myapp", HTTPS: false},
77	}
78
79	baseRoutes := resolveBaseRoutes(routes, domain.PreviewConfig{Separator: "-preview-"})
80	assert.ElementsMatch(t, []baseRouteInfo{
81		{Domain: "app.example.com", HTTPS: true},
82		{Domain: "alias.example.com", HTTPS: false},
83	}, baseRoutes)
84}
85
86func TestResolveBaseRoutes_TreatsSeparatorWithoutBaseAsEligible(t *testing.T) {
87	routes := []domain.Route{
88		{Domain: "my--app.example.com", Image: "myapp", HTTPS: false},
89		{Domain: "other.example.com", Image: "myapp", HTTPS: true},
90	}
91
92	baseRoutes := resolveBaseRoutes(routes, domain.PreviewConfig{Separator: "--"})
93	assert.ElementsMatch(t, []baseRouteInfo{
94		{Domain: "my--app.example.com", HTTPS: false},
95		{Domain: "other.example.com", HTTPS: true},
96	}, baseRoutes)
97}
98
99func TestAutoPreviewHandler_Handle_CreatesPreviewPerBaseRoute(t *testing.T) {
100	store := &captureStore{}
101	svc := NewService(store, time.Hour)
102	h := NewAutoPreviewHandler(t.Context(), &fakeAutoConfigProvider{
103		previewConfig: domain.PreviewConfig{
104			Separator:   "--",
105			TagPatterns: []string{"preview-*"},
106			TTL:         time.Hour,
107		},
108		allowedDomains: []string{"*"},
109		routesByImage: map[string][]domain.Route{
110			"myapp": {
111				{Domain: "app.example.com", Image: "myapp", HTTPS: true},
112				{Domain: "alias.example.com", Image: "myapp", HTTPS: false},
113			},
114		},
115	}, svc)
116
117	err := h.Handle(t.Context(), domain.Event{
118		ID:   "evt-1",
119		Type: domain.EventImagePushed,
120		Data: domain.ImagePushedPayload{Name: "myapp", Reference: "preview-login"},
121	})
122	require.NoError(t, err)
123
124	require.Eventually(t, func() bool {
125		for _, save := range store.saves() {
126			if len(save) != 2 {
127				continue
128			}
129
130			pairs := map[string]domain.PreviewRoute{}
131			for _, preview := range save {
132				pairs[preview.Domain] = preview
133			}
134
135			app, ok := pairs["app--login.example.com"]
136			if !ok || app.BaseRoute != "app.example.com" || !app.HTTPS {
137				continue
138			}
139
140			alias, ok := pairs["alias--login.example.com"]
141			if ok && alias.BaseRoute == "alias.example.com" && !alias.HTTPS {
142				return true
143			}
144		}
145		return false
146	}, time.Second, 10*time.Millisecond)
147}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close