get_budget_controller_test.go raw
1 package controllers
2
3 import (
4 "context"
5 "encoding/json"
6 "testing"
7 "time"
8
9 "github.com/getAlby/go-nostr"
10 "github.com/stretchr/testify/assert"
11 "github.com/stretchr/testify/require"
12
13 "github.com/getAlby/hub/constants"
14 "github.com/getAlby/hub/db"
15 "github.com/getAlby/hub/nip47/models"
16 "github.com/getAlby/hub/tests"
17 )
18
19 const nip47GetBudgetJson = `
20 {
21 "method": "get_budget"
22 }
23 `
24
25 func TestHandleGetBudgetEvent_NoRenewal(t *testing.T) {
26 ctx := context.TODO()
27 svc, err := tests.CreateTestService(t)
28 require.NoError(t, err)
29 defer svc.Remove()
30
31 nip47Request := &models.Request{}
32 err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request)
33 assert.NoError(t, err)
34
35 app, _, err := tests.CreateApp(svc)
36 assert.NoError(t, err)
37
38 appPermission := &db.AppPermission{
39 AppId: app.ID,
40 App: *app,
41 Scope: constants.PAY_INVOICE_SCOPE,
42 MaxAmountSat: 400,
43 BudgetRenewal: constants.BUDGET_RENEWAL_NEVER,
44 }
45 err = svc.DB.Create(appPermission).Error
46 assert.NoError(t, err)
47
48 dbRequestEvent := &db.RequestEvent{}
49 err = svc.DB.Create(&dbRequestEvent).Error
50 assert.NoError(t, err)
51
52 var publishedResponse *models.Response
53
54 publishResponse := func(response *models.Response, tags nostr.Tags) {
55 publishedResponse = response
56 }
57
58 NewTestNip47Controller(svc).
59 HandleGetBudgetEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
60
61 assert.Equal(t, uint64(400000), publishedResponse.Result.(*getBudgetResponse).TotalBudget)
62 assert.Equal(t, uint64(0), publishedResponse.Result.(*getBudgetResponse).UsedBudget)
63 assert.Nil(t, publishedResponse.Result.(*getBudgetResponse).RenewsAt)
64 assert.Equal(t, constants.BUDGET_RENEWAL_NEVER, publishedResponse.Result.(*getBudgetResponse).RenewalPeriod)
65 assert.Nil(t, publishedResponse.Error)
66 }
67
68 func TestHandleGetBudgetEvent_NoneUsed(t *testing.T) {
69 ctx := context.TODO()
70 svc, err := tests.CreateTestService(t)
71 require.NoError(t, err)
72 defer svc.Remove()
73
74 nip47Request := &models.Request{}
75 err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request)
76 assert.NoError(t, err)
77
78 app, _, err := tests.CreateApp(svc)
79 assert.NoError(t, err)
80 now := time.Now()
81
82 appPermission := &db.AppPermission{
83 AppId: app.ID,
84 App: *app,
85 Scope: constants.PAY_INVOICE_SCOPE,
86 MaxAmountSat: 400,
87 BudgetRenewal: constants.BUDGET_RENEWAL_MONTHLY,
88 }
89 err = svc.DB.Create(appPermission).Error
90 assert.NoError(t, err)
91
92 dbRequestEvent := &db.RequestEvent{}
93 err = svc.DB.Create(&dbRequestEvent).Error
94 assert.NoError(t, err)
95
96 var publishedResponse *models.Response
97
98 publishResponse := func(response *models.Response, tags nostr.Tags) {
99 publishedResponse = response
100 }
101
102 NewTestNip47Controller(svc).
103 HandleGetBudgetEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
104
105 assert.Equal(t, uint64(400000), publishedResponse.Result.(*getBudgetResponse).TotalBudget)
106 assert.Equal(t, uint64(0), publishedResponse.Result.(*getBudgetResponse).UsedBudget)
107 renewsAt := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location()).AddDate(0, 1, 0).Unix()
108 assert.Equal(t, uint64(renewsAt), *publishedResponse.Result.(*getBudgetResponse).RenewsAt)
109 assert.Equal(t, constants.BUDGET_RENEWAL_MONTHLY, publishedResponse.Result.(*getBudgetResponse).RenewalPeriod)
110 assert.Nil(t, publishedResponse.Error)
111 }
112
113 func TestHandleGetBudgetEvent_HalfUsed(t *testing.T) {
114 ctx := context.TODO()
115 svc, err := tests.CreateTestService(t)
116 require.NoError(t, err)
117 defer svc.Remove()
118
119 nip47Request := &models.Request{}
120 err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request)
121 assert.NoError(t, err)
122
123 app, _, err := tests.CreateApp(svc)
124 assert.NoError(t, err)
125 now := time.Now()
126
127 appPermission := &db.AppPermission{
128 AppId: app.ID,
129 App: *app,
130 Scope: constants.PAY_INVOICE_SCOPE,
131 MaxAmountSat: 400,
132 BudgetRenewal: constants.BUDGET_RENEWAL_MONTHLY,
133 }
134 err = svc.DB.Create(appPermission).Error
135 assert.NoError(t, err)
136
137 svc.DB.Create(&db.Transaction{
138 AppId: &app.ID,
139 State: constants.TRANSACTION_STATE_SETTLED,
140 Type: constants.TRANSACTION_TYPE_OUTGOING,
141 AmountMsat: 200000,
142 })
143
144 dbRequestEvent := &db.RequestEvent{}
145 err = svc.DB.Create(&dbRequestEvent).Error
146 assert.NoError(t, err)
147
148 var publishedResponse *models.Response
149
150 publishResponse := func(response *models.Response, tags nostr.Tags) {
151 publishedResponse = response
152 }
153
154 NewTestNip47Controller(svc).
155 HandleGetBudgetEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
156
157 assert.Equal(t, uint64(400000), publishedResponse.Result.(*getBudgetResponse).TotalBudget)
158 assert.Equal(t, uint64(200000), publishedResponse.Result.(*getBudgetResponse).UsedBudget)
159 renewsAt := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location()).AddDate(0, 1, 0).Unix()
160 assert.Equal(t, uint64(renewsAt), *publishedResponse.Result.(*getBudgetResponse).RenewsAt)
161 assert.Equal(t, constants.BUDGET_RENEWAL_MONTHLY, publishedResponse.Result.(*getBudgetResponse).RenewalPeriod)
162 assert.Nil(t, publishedResponse.Error)
163 }
164
165 func TestHandleGetBudgetEvent_NoBudget(t *testing.T) {
166 ctx := context.TODO()
167 svc, err := tests.CreateTestService(t)
168 require.NoError(t, err)
169 defer svc.Remove()
170
171 nip47Request := &models.Request{}
172 err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request)
173 assert.NoError(t, err)
174
175 app, _, err := tests.CreateApp(svc)
176 assert.NoError(t, err)
177
178 appPermission := &db.AppPermission{
179 AppId: app.ID,
180 App: *app,
181 Scope: constants.PAY_INVOICE_SCOPE,
182 }
183 err = svc.DB.Create(appPermission).Error
184 assert.NoError(t, err)
185
186 svc.DB.Create(&db.Transaction{
187 AppId: &app.ID,
188 State: constants.TRANSACTION_STATE_SETTLED,
189 Type: constants.TRANSACTION_TYPE_OUTGOING,
190 AmountMsat: 200000,
191 })
192
193 dbRequestEvent := &db.RequestEvent{}
194 err = svc.DB.Create(&dbRequestEvent).Error
195 assert.NoError(t, err)
196
197 var publishedResponse *models.Response
198
199 publishResponse := func(response *models.Response, tags nostr.Tags) {
200 publishedResponse = response
201 }
202
203 NewTestNip47Controller(svc).
204 HandleGetBudgetEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
205
206 assert.Equal(t, struct{}{}, publishedResponse.Result)
207 assert.Nil(t, publishedResponse.Error)
208 }
209
210 func TestHandleGetBudgetEvent_DatabaseError(t *testing.T) {
211 ctx := context.TODO()
212 svc, err := tests.CreateTestService(t)
213 require.NoError(t, err)
214 defer svc.Remove()
215
216 nip47Request := &models.Request{}
217 err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request)
218 assert.NoError(t, err)
219
220 app, _, err := tests.CreateApp(svc)
221 assert.NoError(t, err)
222
223 dbRequestEvent := &db.RequestEvent{}
224 err = svc.DB.Create(&dbRequestEvent).Error
225 assert.NoError(t, err)
226
227 // simulate a database failure that is not a record-not-found error
228 err = svc.DB.Exec("DROP TABLE app_permissions").Error
229 assert.NoError(t, err)
230
231 var publishedResponse *models.Response
232
233 publishResponse := func(response *models.Response, tags nostr.Tags) {
234 publishedResponse = response
235 }
236
237 NewTestNip47Controller(svc).
238 HandleGetBudgetEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
239
240 assert.Nil(t, publishedResponse.Result)
241 require.NotNil(t, publishedResponse.Error)
242 assert.Equal(t, constants.ERROR_INTERNAL, publishedResponse.Error.Code)
243 }
244
245 func TestHandleGetBudgetEvent_NoPayInvoicePermission(t *testing.T) {
246 ctx := context.TODO()
247 svc, err := tests.CreateTestService(t)
248 require.NoError(t, err)
249 defer svc.Remove()
250
251 nip47Request := &models.Request{}
252 err = json.Unmarshal([]byte(nip47GetBudgetJson), nip47Request)
253 assert.NoError(t, err)
254
255 app, _, err := tests.CreateApp(svc)
256 assert.NoError(t, err)
257
258 dbRequestEvent := &db.RequestEvent{}
259 err = svc.DB.Create(&dbRequestEvent).Error
260 assert.NoError(t, err)
261
262 var publishedResponse *models.Response
263
264 publishResponse := func(response *models.Response, tags nostr.Tags) {
265 publishedResponse = response
266 }
267
268 NewTestNip47Controller(svc).
269 HandleGetBudgetEvent(ctx, nip47Request, dbRequestEvent.ID, app, publishResponse)
270
271 assert.Equal(t, struct{}{}, publishedResponse.Result)
272 assert.Nil(t, publishedResponse.Error)
273 }
274