1package config
2
3import (
4 "context"
5 "encoding/json"
6 "errors"
7 "os"
8 "sync"
9 "testing"
10
11 "github.com/charmbracelet/catwalk/pkg/catwalk"
12 "github.com/stretchr/testify/require"
13)
14
15type mockProviderClient struct {
16 shouldFail bool
17 shouldReturnErr error
18}
19
20func (m *mockProviderClient) GetProviders(context.Context, string) ([]catwalk.Provider, error) {
21 if m.shouldReturnErr != nil {
22 return nil, m.shouldReturnErr
23 }
24 if m.shouldFail {
25 return nil, errors.New("failed to load providers")
26 }
27 return []catwalk.Provider{
28 {
29 Name: "Mock",
30 },
31 }, nil
32}
33
34func resetProviderState() {
35 providerOnce = sync.Once{}
36 providerList = nil
37 providerErr = nil
38}
39
40func TestProvider_loadProvidersNoIssues(t *testing.T) {
41 client := &mockProviderClient{shouldFail: false}
42 tmpPath := t.TempDir() + "/providers.json"
43 providers, err := loadProviders(client, "", tmpPath)
44 require.NoError(t, err)
45 require.NotNil(t, providers)
46 require.Len(t, providers, 1)
47
48 // check if file got saved
49 fileInfo, err := os.Stat(tmpPath)
50 require.NoError(t, err)
51 require.False(t, fileInfo.IsDir(), "Expected a file, not a directory")
52}
53
54func TestProvider_DisableAutoUpdate(t *testing.T) {
55 t.Setenv("XDG_DATA_HOME", t.TempDir())
56
57 resetProviderState()
58 defer resetProviderState()
59
60 cfg := &Config{
61 Options: &Options{
62 DisableProviderAutoUpdate: true,
63 },
64 }
65
66 providers, err := Providers(cfg)
67 require.NoError(t, err)
68 require.NotNil(t, providers)
69 require.Greater(t, len(providers), 5, "Expected embedded providers")
70}
71
72func TestProvider_WithValidCache(t *testing.T) {
73 tmpDir := t.TempDir()
74 t.Setenv("XDG_DATA_HOME", tmpDir)
75
76 resetProviderState()
77 defer resetProviderState()
78
79 cachePath := tmpDir + "/crush/providers.json"
80 require.NoError(t, os.MkdirAll(tmpDir+"/crush", 0o755))
81 cachedProviders := []catwalk.Provider{
82 {Name: "Cached"},
83 }
84 data, err := json.Marshal(cachedProviders)
85 require.NoError(t, err)
86 require.NoError(t, os.WriteFile(cachePath, data, 0o644))
87
88 mockClient := &mockProviderClient{shouldFail: false}
89
90 providers, err := loadProviders(mockClient, "", cachePath)
91 require.NoError(t, err)
92 require.NotNil(t, providers)
93 require.Len(t, providers, 1)
94 require.Equal(t, "Mock", providers[0].Name, "Expected fresh provider from fetch")
95}
96
97func TestProvider_NotModifiedUsesCached(t *testing.T) {
98 tmpDir := t.TempDir()
99 t.Setenv("XDG_DATA_HOME", tmpDir)
100
101 resetProviderState()
102 defer resetProviderState()
103
104 cachePath := tmpDir + "/crush/providers.json"
105 require.NoError(t, os.MkdirAll(tmpDir+"/crush", 0o755))
106 cachedProviders := []catwalk.Provider{
107 {Name: "Cached"},
108 }
109 data, err := json.Marshal(cachedProviders)
110 require.NoError(t, err)
111 require.NoError(t, os.WriteFile(cachePath, data, 0o644))
112
113 mockClient := &mockProviderClient{shouldReturnErr: catwalk.ErrNotModified}
114 providers, err := loadProviders(mockClient, "", cachePath)
115 require.ErrorIs(t, err, catwalk.ErrNotModified)
116 require.Nil(t, providers)
117}
118
119func TestProvider_EmptyCacheDefaultsToEmbedded(t *testing.T) {
120 tmpDir := t.TempDir()
121 t.Setenv("XDG_DATA_HOME", tmpDir)
122
123 resetProviderState()
124 defer resetProviderState()
125
126 cachePath := tmpDir + "/crush/providers.json"
127 require.NoError(t, os.MkdirAll(tmpDir+"/crush", 0o755))
128 emptyProviders := []catwalk.Provider{}
129 data, err := json.Marshal(emptyProviders)
130 require.NoError(t, err)
131 require.NoError(t, os.WriteFile(cachePath, data, 0o644))
132
133 cached, _, err := loadProvidersFromCache(cachePath)
134 require.NoError(t, err)
135 require.Empty(t, cached, "Expected empty cache")
136}
137
138func TestProvider_loadProvidersWithIssuesAndNoCache(t *testing.T) {
139 client := &mockProviderClient{shouldFail: true}
140 tmpPath := t.TempDir() + "/providers.json"
141 providers, err := loadProviders(client, "", tmpPath)
142 require.Error(t, err)
143 require.Nil(t, providers, "Expected nil providers when loading fails and no cache exists")
144}