Skip to content

Commit 36d273f

Browse files
committed
add tests
1 parent cb8be88 commit 36d273f

File tree

1 file changed

+380
-0
lines changed

1 file changed

+380
-0
lines changed
Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
// Copyright 2024, Pulumi Corporation.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package svc
16+
17+
import (
18+
"context"
19+
"encoding/json"
20+
"net/http"
21+
"net/http/httptest"
22+
"os"
23+
"path/filepath"
24+
"testing"
25+
"time"
26+
27+
"github.com/ghodss/yaml"
28+
"github.com/stretchr/testify/assert"
29+
"github.com/stretchr/testify/require"
30+
31+
"github.com/pulumi/registry/tools/resourcedocsgen/pkg"
32+
)
33+
34+
func stringPtr(s string) *string {
35+
return &s
36+
}
37+
38+
func TestConvertAPIPackageToPackageMeta(t *testing.T) {
39+
createdAt := time.Date(2025, 4, 10, 12, 0, 0, 0, time.UTC)
40+
tests := []struct {
41+
name string
42+
input PackageMetadata
43+
want pkg.PackageMeta
44+
wantErr bool
45+
}{
46+
{
47+
name: "provider package",
48+
input: PackageMetadata{
49+
Name: "aws",
50+
Publisher: "Pulumi",
51+
Description: "AWS provider",
52+
LogoURL: "https://example.com/logo.png",
53+
RepoURL: "https://github.com/pulumi/pulumi-aws",
54+
Category: "cloud",
55+
IsFeatured: true,
56+
PackageTypes: []string{"native"},
57+
SchemaURL: "https://example.com/schema.json",
58+
Version: "v1.0.0",
59+
Title: "AWS",
60+
CreatedAt: createdAt,
61+
},
62+
want: pkg.PackageMeta{
63+
Name: "aws",
64+
Publisher: "Pulumi",
65+
Description: "AWS provider",
66+
LogoURL: "https://example.com/logo.png",
67+
RepoURL: "https://github.com/pulumi/pulumi-aws",
68+
Category: "cloud",
69+
Featured: true,
70+
Native: true,
71+
Component: false,
72+
SchemaFileURL: "https://example.com/schema.json",
73+
Version: "v1.0.0",
74+
Title: "AWS",
75+
UpdatedOn: createdAt.Unix(),
76+
},
77+
},
78+
{
79+
name: "component package",
80+
input: PackageMetadata{
81+
Name: "kubernetes-app",
82+
PackageTypes: []string{"component"},
83+
CreatedAt: createdAt,
84+
},
85+
want: pkg.PackageMeta{
86+
Name: "kubernetes-app",
87+
Component: true,
88+
Native: false,
89+
UpdatedOn: createdAt.Unix(),
90+
},
91+
},
92+
}
93+
94+
for _, tt := range tests {
95+
t.Run(tt.name, func(t *testing.T) {
96+
got, err := convertAPIPackageToPackageMeta(tt.input)
97+
if tt.wantErr {
98+
assert.Error(t, err)
99+
return
100+
}
101+
require.NoError(t, err)
102+
assert.Equal(t, tt.want, *got)
103+
})
104+
}
105+
}
106+
107+
func TestFileSystemProvider(t *testing.T) {
108+
// Create a temporary directory for test files
109+
tmpDir := t.TempDir()
110+
packagesDir := filepath.Join(tmpDir, "themes", "default", "data", "registry", "packages")
111+
require.NoError(t, os.MkdirAll(packagesDir, 0755))
112+
113+
// Create test metadata files
114+
testPackages := []pkg.PackageMeta{
115+
{
116+
Name: "aws",
117+
Publisher: "Pulumi",
118+
Version: "v1.0.0",
119+
UpdatedOn: time.Now().Unix(),
120+
Native: true,
121+
Component: false,
122+
Category: "cloud",
123+
Featured: true,
124+
},
125+
{
126+
Name: "kubernetes",
127+
Publisher: "Pulumi",
128+
Version: "v2.0.0",
129+
UpdatedOn: time.Now().Unix(),
130+
Native: true,
131+
Component: false,
132+
Category: "cloud",
133+
Featured: true,
134+
},
135+
}
136+
137+
for _, p := range testPackages {
138+
data, err := yaml.Marshal(p)
139+
require.NoError(t, err)
140+
err = os.WriteFile(filepath.Join(packagesDir, p.Name+".yaml"), data, 0755)
141+
require.NoError(t, err)
142+
}
143+
144+
provider := NewFileSystemProvider(tmpDir)
145+
146+
t.Run("GetPackageMetadata", func(t *testing.T) {
147+
got, err := provider.GetPackageMetadata(context.Background(), "aws")
148+
require.NoError(t, err)
149+
assert.Equal(t, testPackages[0], got)
150+
151+
_, err = provider.GetPackageMetadata(context.Background(), "non-existent pkg")
152+
assert.Error(t, err)
153+
})
154+
155+
t.Run("ListPackageMetadata", func(t *testing.T) {
156+
got, err := provider.ListPackageMetadata(context.Background())
157+
require.NoError(t, err)
158+
assert.Len(t, got, len(testPackages))
159+
assert.ElementsMatch(t, testPackages, got)
160+
})
161+
162+
t.Run("GetPackageMetadata errors", func(t *testing.T) {
163+
t.Run("non-existent file", func(t *testing.T) {
164+
provider := NewFileSystemProvider(tmpDir)
165+
_, err := provider.GetPackageMetadata(context.Background(), "non-existent")
166+
assert.Error(t, err)
167+
assert.Contains(t, err.Error(), "reading the metadata file")
168+
})
169+
170+
t.Run("invalid yaml", func(t *testing.T) {
171+
err := os.WriteFile(filepath.Join(packagesDir, "invalid.yaml"), []byte("invalid yaml: ]["), 0755)
172+
require.NoError(t, err)
173+
174+
provider := NewFileSystemProvider(tmpDir)
175+
_, err = provider.GetPackageMetadata(context.Background(), "invalid")
176+
assert.Error(t, err)
177+
assert.Contains(t, err.Error(), "unmarshalling the metadata file")
178+
})
179+
})
180+
181+
t.Run("ListPackageMetadata errors", func(t *testing.T) {
182+
t.Run("non-existent directory", func(t *testing.T) {
183+
tmpDir := t.TempDir()
184+
provider := NewFileSystemProvider(tmpDir)
185+
_, err := provider.ListPackageMetadata(context.Background())
186+
assert.Error(t, err)
187+
assert.Contains(t, err.Error(), "reading directory")
188+
})
189+
190+
t.Run("ignores non-yaml files", func(t *testing.T) {
191+
tmpDir := t.TempDir()
192+
packagesDir := filepath.Join(tmpDir, "themes", "default", "data", "registry", "packages")
193+
require.NoError(t, os.MkdirAll(packagesDir, 0755))
194+
195+
// Create a valid yaml file
196+
validPkg := pkg.PackageMeta{Name: "valid", Publisher: "Pulumi"}
197+
validYAML, err := yaml.Marshal(validPkg)
198+
require.NoError(t, err)
199+
err = os.WriteFile(filepath.Join(packagesDir, "valid.yaml"), validYAML, 0755)
200+
require.NoError(t, err)
201+
202+
// Create an invalid yaml file
203+
err = os.WriteFile(filepath.Join(packagesDir, "readme.txt"), []byte("not valid yaml"), 0755)
204+
require.NoError(t, err)
205+
206+
provider := NewFileSystemProvider(tmpDir)
207+
packages, err := provider.ListPackageMetadata(context.Background())
208+
require.NoError(t, err)
209+
assert.Len(t, packages, 1)
210+
assert.Equal(t, "valid", packages[0].Name)
211+
})
212+
})
213+
}
214+
215+
func TestRegistryAPIProvider(t *testing.T) {
216+
t.Run("GetPackageMetadata", func(t *testing.T) {
217+
t.Run("successfully returns package metadata", func(t *testing.T) {
218+
// configure test server
219+
expectedPackage := PackageMetadata{
220+
Name: "aws-test",
221+
Publisher: "Pulumi",
222+
Version: "v1.0.0",
223+
CreatedAt: time.Now(),
224+
}
225+
responseBody := PackageListResponse{
226+
Packages: []PackageMetadata{expectedPackage},
227+
}
228+
jsonResponse, err := json.Marshal(responseBody)
229+
require.NoError(t, err)
230+
231+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
232+
assert.Equal(t, "/packages", r.URL.Path)
233+
assert.Equal(t, "name=aws-test", r.URL.RawQuery)
234+
w.WriteHeader(http.StatusOK)
235+
w.Write(jsonResponse)
236+
}))
237+
defer server.Close()
238+
239+
// rreate client using test server
240+
provider := &registryAPIProvider{
241+
apiURL: server.URL,
242+
client: http.DefaultClient,
243+
}
244+
245+
got, err := provider.GetPackageMetadata(context.Background(), "aws-test")
246+
require.NoError(t, err)
247+
assert.Equal(t, "aws-test", got.Name)
248+
assert.Equal(t, "Pulumi", got.Publisher)
249+
})
250+
251+
t.Run("non existent package", func(t *testing.T) {
252+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
253+
w.WriteHeader(http.StatusNotFound)
254+
}))
255+
defer server.Close()
256+
257+
provider := &registryAPIProvider{
258+
apiURL: server.URL,
259+
client: http.DefaultClient,
260+
}
261+
262+
_, err := provider.GetPackageMetadata(context.Background(), "non-existent-pkg")
263+
assert.Error(t, err)
264+
})
265+
266+
t.Run("multiple packages found", func(t *testing.T) {
267+
// Setup response with multiple packages
268+
response := PackageListResponse{
269+
Packages: []PackageMetadata{
270+
{Name: "aws-test", Publisher: "Pulumi"},
271+
{Name: "aws-test", Publisher: "Community"},
272+
},
273+
}
274+
jsonResponse, err := json.Marshal(response)
275+
require.NoError(t, err)
276+
277+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
278+
w.WriteHeader(http.StatusOK)
279+
w.Write(jsonResponse)
280+
}))
281+
defer server.Close()
282+
283+
provider := &registryAPIProvider{
284+
apiURL: server.URL,
285+
client: http.DefaultClient,
286+
}
287+
288+
_, err = provider.GetPackageMetadata(context.Background(), "aws-test")
289+
assert.Error(t, err)
290+
assert.Contains(t, err.Error(), "multiple packages found")
291+
})
292+
})
293+
294+
t.Run("ListPackageMetadata", func(t *testing.T) {
295+
t.Run("successfully lists packages with pagination", func(t *testing.T) {
296+
// configure to test with pagination
297+
firstPage := struct {
298+
Packages []PackageMetadata `json:"packages"`
299+
ContinuationToken *string `json:"continuationToken"`
300+
}{
301+
Packages: []PackageMetadata{
302+
{Name: "aws-test", Publisher: "Pulumi"},
303+
{Name: "azure-test", Publisher: "Pulumi"},
304+
},
305+
ContinuationToken: stringPtr("page2"),
306+
}
307+
firstPageJSON, err := json.Marshal(firstPage)
308+
require.NoError(t, err)
309+
310+
secondPage := struct {
311+
Packages []PackageMetadata `json:"packages"`
312+
ContinuationToken *string `json:"continuationToken"`
313+
}{
314+
Packages: []PackageMetadata{
315+
{Name: "gcp-test", Publisher: "Pulumi"},
316+
},
317+
ContinuationToken: nil,
318+
}
319+
secondPageJSON, err := json.Marshal(secondPage)
320+
require.NoError(t, err)
321+
322+
// setup test server
323+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
324+
assert.Equal(t, "/packages", r.URL.Path)
325+
w.WriteHeader(http.StatusOK)
326+
327+
// Return different responses based on continuation token
328+
if r.URL.Query().Get("continuationToken") == "page2" {
329+
w.Write(secondPageJSON)
330+
} else {
331+
w.Write(firstPageJSON)
332+
}
333+
}))
334+
defer server.Close()
335+
336+
provider := &registryAPIProvider{
337+
apiURL: server.URL,
338+
client: http.DefaultClient,
339+
}
340+
341+
got, err := provider.ListPackageMetadata(context.Background())
342+
require.NoError(t, err)
343+
assert.Len(t, got, 3)
344+
assert.Equal(t, []string{"aws-test", "azure-test", "gcp-test"}, []string{got[0].Name, got[1].Name, got[2].Name})
345+
})
346+
347+
t.Run("invalid json response", func(t *testing.T) {
348+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
349+
w.WriteHeader(http.StatusOK)
350+
w.Write([]byte("invalid json"))
351+
}))
352+
defer server.Close()
353+
354+
provider := &registryAPIProvider{
355+
apiURL: server.URL,
356+
client: http.DefaultClient,
357+
}
358+
359+
_, err := provider.ListPackageMetadata(context.Background())
360+
assert.Error(t, err)
361+
assert.Contains(t, err.Error(), "decoding API response")
362+
})
363+
364+
t.Run("500 server error", func(t *testing.T) {
365+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
366+
w.WriteHeader(http.StatusInternalServerError)
367+
}))
368+
defer server.Close()
369+
370+
provider := &registryAPIProvider{
371+
apiURL: server.URL,
372+
client: http.DefaultClient,
373+
}
374+
375+
_, err := provider.ListPackageMetadata(context.Background())
376+
assert.Error(t, err)
377+
assert.Contains(t, err.Error(), "unexpected status code 500")
378+
})
379+
})
380+
}

0 commit comments

Comments
 (0)