import { of } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { CalculatorPageComponent } from './calculator-page.component'; import { QuoteEstimatorService, QuoteResult, } from './services/quote-estimator.service'; import { LanguageService } from '../../core/services/language.service'; import { UploadFormComponent } from './components/upload-form/upload-form.component'; describe('CalculatorPageComponent', () => { const createResult = (sessionId: string, notes?: string): QuoteResult => ({ sessionId, items: [ { id: 'line-1', fileName: 'part-a.stl', unitPrice: 4, unitTime: 120, unitWeight: 2, quantity: 1, }, ], setupCost: 2, globalMachineCost: 0, currency: 'CHF', totalPrice: 6, totalTimeHours: 0, totalTimeMinutes: 2, totalWeight: 2, notes, }); function createComponent() { const estimator = jasmine.createSpyObj( 'QuoteEstimatorService', ['updateLineItem', 'getQuoteSession', 'mapSessionToQuoteResult'], ); const router = jasmine.createSpyObj('Router', ['navigate']); const route = { data: of({}), queryParams: of({}), } as unknown as ActivatedRoute; const languageService = jasmine.createSpyObj( 'LanguageService', ['selectedLang'], ); const component = new CalculatorPageComponent( estimator, router, route, languageService, ); const uploadForm = jasmine.createSpyObj( 'UploadFormComponent', ['updateItemQuantityByIndex', 'updateItemQuantityByName'], ); component.uploadForm = uploadForm; return { component, estimator, uploadForm, }; } it('updates left panel quantities even when item id is missing', () => { const { component, estimator, uploadForm } = createComponent(); component.onItemChange({ index: 0, fileName: 'part-a.stl', quantity: 4, }); expect(uploadForm.updateItemQuantityByIndex).toHaveBeenCalledWith(0, 4); expect(uploadForm.updateItemQuantityByName).toHaveBeenCalledWith( 'part-a.stl', 4, ); expect(estimator.updateLineItem).not.toHaveBeenCalled(); }); it('refreshes quote totals after successful line item update', () => { const { component, estimator } = createComponent(); component.result.set(createResult('session-1', 'persisted notes')); estimator.updateLineItem.and.returnValue(of({ ok: true })); estimator.getQuoteSession.and.returnValue(of({ session: { id: 'session-1' } })); estimator.mapSessionToQuoteResult.and.returnValue(createResult('session-1')); component.onItemChange({ id: 'line-1', index: 0, fileName: 'part-a.stl', quantity: 7, }); expect(estimator.updateLineItem).toHaveBeenCalledWith('line-1', { quantity: 7, }); expect(estimator.getQuoteSession).toHaveBeenCalledWith('session-1'); expect(component.result()?.notes).toBe('persisted notes'); expect(component.result()?.items[0].quantity).toBe(1); }); });