diff --git a/libs/ui/src/lib/services/data.service.spec.ts b/libs/ui/src/lib/services/data.service.spec.ts new file mode 100644 index 000000000..98c85f2f9 --- /dev/null +++ b/libs/ui/src/lib/services/data.service.spec.ts @@ -0,0 +1,83 @@ +import { CreateBudgetDto, UpdateBudgetDto } from '@ghostfolio/common/dtos'; + +import { + provideHttpClient, + withInterceptorsFromDi +} from '@angular/common/http'; +import { + HttpTestingController, + provideHttpClientTesting +} from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; + +import { DataService } from './data.service'; + +describe('DataService budget methods', () => { + let dataService: DataService; + let httpTestingController: HttpTestingController; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + DataService, + provideHttpClient(withInterceptorsFromDi()), + provideHttpClientTesting() + ] + }); + + dataService = TestBed.inject(DataService); + httpTestingController = TestBed.inject(HttpTestingController); + }); + + afterEach(() => { + httpTestingController.verify(); + }); + + it('fetches budgets for a month', () => { + dataService.fetchBudgets({ month: '2026-06' }).subscribe(); + + const request = httpTestingController.expectOne( + '/api/v1/budgets?month=2026-06' + ); + + expect(request.request.method).toBe('GET'); + }); + + it('creates a budget', () => { + const budget: CreateBudgetDto = { + amount: 500, + categoryId: 'category-1', + month: '2026-06' + }; + + dataService.createBudget(budget).subscribe(); + + const request = httpTestingController.expectOne('/api/v1/budgets'); + + expect(request.request.method).toBe('POST'); + expect(request.request.body).toEqual(budget); + }); + + it('updates a budget', () => { + const budget: UpdateBudgetDto = { + amount: 650, + categoryId: 'category-1', + month: '2026-06' + }; + + dataService.updateBudget({ budget, id: 'budget-1' }).subscribe(); + + const request = httpTestingController.expectOne('/api/v1/budgets/budget-1'); + + expect(request.request.method).toBe('PUT'); + expect(request.request.body).toEqual(budget); + }); + + it('deletes a budget', () => { + dataService.deleteBudget('budget-1').subscribe(); + + const request = httpTestingController.expectOne('/api/v1/budgets/budget-1'); + + expect(request.request.method).toBe('DELETE'); + }); +}); diff --git a/libs/ui/src/lib/services/data.service.ts b/libs/ui/src/lib/services/data.service.ts index 8d16c6d35..878e554c5 100644 --- a/libs/ui/src/lib/services/data.service.ts +++ b/libs/ui/src/lib/services/data.service.ts @@ -2,6 +2,7 @@ import { CreateAccessDto, CreateAccountBalanceDto, CreateAccountDto, + CreateBudgetDto, CreateOrderDto, CreateTagDto, CreateWatchlistItemDto, @@ -9,6 +10,7 @@ import { TransferBalanceDto, UpdateAccessDto, UpdateAccountDto, + UpdateBudgetDto, UpdateBulkMarketDataDto, UpdateOrderDto, UpdateOwnAccessTokenDto, @@ -33,6 +35,8 @@ import { AssetResponse, BenchmarkMarketDataDetailsResponse, BenchmarkResponse, + BudgetResponse, + BudgetsResponse, CreateStripeCheckoutSessionResponse, DataProviderHealthResponse, DataProviderHistoricalResponse, @@ -193,6 +197,14 @@ export class DataService { ); } + public createBudget(budget: CreateBudgetDto) { + return this.http.post('/api/v1/budgets', budget); + } + + public deleteBudget(id: string) { + return this.http.delete(`/api/v1/budgets/${id}`); + } + public fetchAccount(aAccountId: string) { return this.http.get(`/api/v1/account/${aAccountId}`); } @@ -379,6 +391,16 @@ export class DataService { ); } + public fetchBudgets({ month }: { month?: string } = {}) { + let params = new HttpParams(); + + if (month) { + params = params.append('month', month); + } + + return this.http.get('/api/v1/budgets', { params }); + } + public fetchAssetProfiles({ filters, skip, @@ -935,6 +957,10 @@ export class DataService { ); } + public updateBudget({ budget, id }: { budget: UpdateBudgetDto; id: string }) { + return this.http.put(`/api/v1/budgets/${id}`, budget); + } + public updateInfo() { this.http.get('/api/v1/info').subscribe((info) => { const utmSource = window.localStorage.getItem('utm_source') as