Skip to content

Commit 5a5e59d

Browse files
committed
test: enhance invoice handling tests with PDF generation and file storage validation
1 parent ca59955 commit 5a5e59d

File tree

2 files changed

+142
-6
lines changed

2 files changed

+142
-6
lines changed

backend/app/invoice_handler_test.go

Lines changed: 141 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,28 @@ package app
33
import (
44
"encoding/json"
55
"fmt"
6+
"kubecloud/internal"
7+
"kubecloud/models"
68
"net/http"
79
"net/http/httptest"
10+
"os"
11+
"path/filepath"
812
"testing"
913
"time"
1014

1115
"github.com/stretchr/testify/assert"
1216
"github.com/stretchr/testify/require"
13-
14-
"kubecloud/models"
1517
)
1618

1719
func TestListAllInvoicesHandler(t *testing.T) {
1820
app, err := SetUp(t)
1921
require.NoError(t, err)
2022
router := app.router
2123

22-
adminUser := CreateTestUser(t, app, "[email protected]", "Admin User", []byte("securepassword"), true, true, false, 0, time.Now())
23-
nonAdminUser := CreateTestUser(t, app, "[email protected]", "Normal User", []byte("securepassword"), true, false, false, 0, time.Now())
24+
require.NotNil(t, app.handlers.fileStorage)
25+
26+
adminUser := CreateTestUser(t, app, "[email protected]", "Admin User", []byte("securepassword"), true, true, true, 0, time.Now())
27+
nonAdminUser := CreateTestUser(t, app, "[email protected]", "Normal User", []byte("securepassword"), true, false, true, 0, time.Now())
2428

2529
t.Run("Test List all invoices with empty list", func(t *testing.T) {
2630
token := GetAuthToken(t, app, adminUser.ID, adminUser.Email, adminUser.Username, true)
@@ -62,6 +66,16 @@ func TestListAllInvoicesHandler(t *testing.T) {
6266
err = app.handlers.db.CreateInvoice(invoice2)
6367
require.NoError(t, err)
6468

69+
pdf1, err := internal.CreateInvoicePDF(*invoice1, *adminUser, app.config.Invoice)
70+
require.NoError(t, err)
71+
pdf2, err := internal.CreateInvoicePDF(*invoice2, *nonAdminUser, app.config.Invoice)
72+
require.NoError(t, err)
73+
74+
_, err = app.handlers.fileStorage.WriteInvoiceFile(adminUser.ID, invoice1.ID, pdf1)
75+
require.NoError(t, err)
76+
_, err = app.handlers.fileStorage.WriteInvoiceFile(nonAdminUser.ID, invoice2.ID, pdf2)
77+
require.NoError(t, err)
78+
6579
t.Run("Test List all invoices successfully", func(t *testing.T) {
6680
token := GetAuthToken(t, app, adminUser.ID, adminUser.Email, adminUser.Username, true)
6781
req, _ := http.NewRequest("GET", "/api/v1/invoices", nil)
@@ -95,6 +109,18 @@ func TestListAllInvoicesHandler(t *testing.T) {
95109
}
96110
assert.True(t, found1, "Admin's invoice should be in the list")
97111
assert.True(t, found2, "Normal user's invoice should be in the list")
112+
113+
storedPDF1, err := app.handlers.fileStorage.ReadInvoiceFile(adminUser.ID, invoice1.ID)
114+
require.NoError(t, err)
115+
assert.Equal(t, pdf1, storedPDF1)
116+
assert.Greater(t, len(storedPDF1), 100)
117+
118+
storedPDF2, err := app.handlers.fileStorage.ReadInvoiceFile(nonAdminUser.ID, invoice2.ID)
119+
require.NoError(t, err)
120+
assert.Equal(t, pdf2, storedPDF2)
121+
assert.Greater(t, len(storedPDF2), 100)
122+
123+
assert.NotEqual(t, storedPDF1, storedPDF2)
98124
})
99125

100126
t.Run("Test List all invoices with no token", func(t *testing.T) {
@@ -119,7 +145,7 @@ func TestListUserInvoicesHandler(t *testing.T) {
119145
require.NoError(t, err)
120146
router := app.router
121147

122-
user := CreateTestUser(t, app, "[email protected]", "Test User", []byte("securepassword"), true, false, false, 0, time.Now())
148+
user := CreateTestUser(t, app, "[email protected]", "Test User", []byte("securepassword"), true, false, true, 0, time.Now())
123149

124150
t.Run("Test List user invoices with empty list", func(t *testing.T) {
125151
token := GetAuthToken(t, app, user.ID, user.Email, user.Username, false)
@@ -153,6 +179,13 @@ func TestListUserInvoicesHandler(t *testing.T) {
153179
err = app.handlers.db.CreateInvoice(invoice1)
154180
require.NoError(t, err)
155181

182+
pdfContent, err := internal.CreateInvoicePDF(*invoice1, *user, app.config.Invoice)
183+
require.NoError(t, err)
184+
require.NotEmpty(t, pdfContent)
185+
186+
_, err = app.handlers.fileStorage.WriteInvoiceFile(user.ID, invoice1.ID, pdfContent)
187+
require.NoError(t, err)
188+
156189
t.Run("Test List user invoices successfully", func(t *testing.T) {
157190
token := GetAuthToken(t, app, user.ID, user.Email, user.Username, false)
158191
req, _ := http.NewRequest("GET", "/api/v1/user/invoice", nil)
@@ -164,6 +197,15 @@ func TestListUserInvoicesHandler(t *testing.T) {
164197
err := json.Unmarshal(resp.Body.Bytes(), &result)
165198
assert.NoError(t, err)
166199
assert.Equal(t, "Invoices are retrieved successfully", result["message"])
200+
201+
data := result["data"].(map[string]interface{})
202+
invoicesRaw := data["invoices"].([]interface{})
203+
assert.Len(t, invoicesRaw, 1)
204+
205+
storedPDF, err := app.handlers.fileStorage.ReadInvoiceFile(user.ID, invoice1.ID)
206+
require.NoError(t, err)
207+
assert.Equal(t, pdfContent, storedPDF)
208+
assert.Greater(t, len(storedPDF), 100)
167209
})
168210

169211
t.Run("Test List user invoices with no token", func(t *testing.T) {
@@ -180,6 +222,8 @@ func TestDownloadInvoiceHandler(t *testing.T) {
180222
require.NoError(t, err)
181223
router := app.router
182224

225+
require.NotNil(t, app.handlers.fileStorage)
226+
183227
user1 := CreateTestUser(t, app, "[email protected]", "User One", []byte("securepassword"), true, false, false, 0, time.Now())
184228

185229
invoice := &models.Invoice{
@@ -193,14 +237,44 @@ func TestDownloadInvoiceHandler(t *testing.T) {
193237
require.NoError(t, err)
194238

195239
t.Run("Download an invoice successfully", func(t *testing.T) {
240+
pdfContent, err := internal.CreateInvoicePDF(*invoice, *user1, app.config.Invoice)
241+
require.NoError(t, err)
242+
require.NotEmpty(t, pdfContent)
243+
require.Greater(t, len(pdfContent), 100)
244+
245+
fileName, err := app.handlers.fileStorage.WriteInvoiceFile(user1.ID, invoice.ID, pdfContent)
246+
require.NoError(t, err)
247+
assert.Contains(t, fileName, fmt.Sprintf("user-%d", user1.ID))
248+
assert.Contains(t, fileName, fmt.Sprintf("invoice-%d", invoice.ID))
249+
250+
filePath := filepath.Join(app.config.FileStoragePath, "invoices", fileName)
251+
assert.FileExists(t, filePath)
252+
253+
fileInfo, err := os.Stat(filePath)
254+
require.NoError(t, err)
255+
assert.Equal(t, os.FileMode(0o600), fileInfo.Mode().Perm())
256+
196257
token := GetAuthToken(t, app, user1.ID, user1.Email, user1.Username, false)
197258
req, _ := http.NewRequest("GET", fmt.Sprintf("/api/v1/user/invoice/%d", invoice.ID), nil)
198259
req.Header.Set("Authorization", "Bearer "+token)
199260
resp := httptest.NewRecorder()
200261
router.ServeHTTP(resp, req)
262+
201263
assert.Equal(t, http.StatusOK, resp.Code)
202264
assert.Equal(t, "application/pdf", resp.Header().Get("Content-Type"))
203-
assert.True(t, len(resp.Body.Bytes()) > 0)
265+
266+
responseBody := resp.Body.Bytes()
267+
assert.NotEmpty(t, responseBody)
268+
assert.Greater(t, len(responseBody), 100)
269+
assert.Equal(t, pdfContent, responseBody)
270+
271+
if len(responseBody) >= 4 {
272+
assert.Equal(t, "%PDF", string(responseBody[:4]))
273+
}
274+
275+
contentDisposition := resp.Header().Get("Content-Disposition")
276+
assert.Contains(t, contentDisposition, "attachment")
277+
assert.Contains(t, contentDisposition, fileName)
204278
})
205279

206280
t.Run("Download invoice with no token", func(t *testing.T) {
@@ -228,4 +302,65 @@ func TestDownloadInvoiceHandler(t *testing.T) {
228302
router.ServeHTTP(resp, req)
229303
assert.Equal(t, http.StatusBadRequest, resp.Code)
230304
})
305+
306+
t.Run("Download invoice missing from file storage generates on-demand", func(t *testing.T) {
307+
user2 := CreateTestUser(t, app, "[email protected]", "User Two", []byte("password"), true, false, true, 0, time.Now())
308+
309+
invoice2 := &models.Invoice{
310+
UserID: user2.ID,
311+
Total: 99.99,
312+
Tax: 9.99,
313+
CreatedAt: time.Now(),
314+
}
315+
err := app.db.CreateInvoice(invoice2)
316+
require.NoError(t, err)
317+
318+
token := GetAuthToken(t, app, user2.ID, user2.Email, user2.Username, false)
319+
req, _ := http.NewRequest("GET", fmt.Sprintf("/api/v1/user/invoice/%d", invoice2.ID), nil)
320+
req.Header.Set("Authorization", "Bearer "+token)
321+
resp := httptest.NewRecorder()
322+
router.ServeHTTP(resp, req)
323+
324+
assert.Equal(t, http.StatusOK, resp.Code)
325+
assert.Equal(t, "application/pdf", resp.Header().Get("Content-Type"))
326+
327+
responseBody := resp.Body.Bytes()
328+
assert.NotEmpty(t, responseBody)
329+
assert.Greater(t, len(responseBody), 100)
330+
331+
if len(responseBody) >= 4 {
332+
assert.Equal(t, "%PDF", string(responseBody[:4]))
333+
}
334+
335+
storedContent, err := app.handlers.fileStorage.ReadInvoiceFile(user2.ID, invoice2.ID)
336+
require.NoError(t, err)
337+
assert.Equal(t, responseBody, storedContent)
338+
})
339+
340+
t.Run("User cannot download another user's invoice", func(t *testing.T) {
341+
user3 := CreateTestUser(t, app, "[email protected]", "User Three", []byte("password"), true, false, true, 0, time.Now())
342+
343+
invoice3 := &models.Invoice{
344+
UserID: user1.ID,
345+
Total: 250.00,
346+
Tax: 25.00,
347+
CreatedAt: time.Now(),
348+
}
349+
err := app.db.CreateInvoice(invoice3)
350+
require.NoError(t, err)
351+
352+
pdfContent, err := internal.CreateInvoicePDF(*invoice3, *user1, app.config.Invoice)
353+
require.NoError(t, err)
354+
_, err = app.handlers.fileStorage.WriteInvoiceFile(user1.ID, invoice3.ID, pdfContent)
355+
require.NoError(t, err)
356+
357+
token := GetAuthToken(t, app, user3.ID, user3.Email, user3.Username, false)
358+
req, _ := http.NewRequest("GET", fmt.Sprintf("/api/v1/user/invoice/%d", invoice3.ID), nil)
359+
req.Header.Set("Authorization", "Bearer "+token)
360+
resp := httptest.NewRecorder()
361+
router.ServeHTTP(resp, req)
362+
363+
assert.Equal(t, http.StatusForbidden, resp.Code)
364+
assert.NotEqual(t, "application/pdf", resp.Header().Get("Content-Type"))
365+
})
231366
}

backend/internal/filestorage_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ func TestWriteAndReadInvoiceFile(t *testing.T) {
9191

9292
_, err = service.WriteInvoiceFile(userID, invoiceID, updatedData)
9393
assert.NoError(t, err)
94+
9495
readData, err := service.ReadInvoiceFile(userID, invoiceID)
9596
assert.NoError(t, err)
9697
assert.Equal(t, updatedData, readData)

0 commit comments

Comments
 (0)