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