Skip to content

Commit

Permalink
Wfprev 107 c (#469)
Browse files Browse the repository at this point in the history
  • Loading branch information
yzlucas authored Jan 30, 2025
1 parent b5f0785 commit a261e27
Show file tree
Hide file tree
Showing 9 changed files with 4,369 additions and 2,798 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="fiscals-container">
<div>
<div class="button-row">
<button mat-raised-button class="primary" (click)="addNewFiscal()">
<button mat-raised-button class="primary new-fiscal-button" (click)="addNewFiscal()">
<img alt="create-project" class="icon" src="/assets/add-button.svg" width="19" height="19">
Add New Fiscal
</button>
Expand All @@ -10,8 +10,26 @@
<mat-tab *ngFor="let fiscal of projectFiscals; let i = index" [label]="fiscal.fiscalYearFormatted || 'New Fiscal'">
<mat-expansion-panel [expanded]="true" class="fiscal-expansion-panel">
<mat-expansion-panel-header>
<span class="project-title">Fiscal Detail</span>
<div class="header-container">
<span class="project-title">Fiscal Detail</span>
<button class="dropdown-button" mat-icon-button [matMenuTriggerFor]="menu" (click)="$event.stopPropagation()">
<!-- Three-dot menu icon -->
<span>Actions</span>
<img class="action-icon" alt="actions" src="/assets/dropdown-icon-white.svg">
</button>
</div>
</mat-expansion-panel-header>
<mat-menu #menu="matMenu">
<button mat-menu-item>
Delete Fiscal Year
</button>
<button mat-menu-item >
Add Performance Update
</button>
<button mat-menu-item >
Closeout Fiscal
</button>
</mat-menu>
<form class="form-grid" [formGroup]="fiscalForms[i]">

<div class="form-item">
Expand Down Expand Up @@ -101,12 +119,12 @@
</div>

<div class="form-item half-width">
<label>Description</label>
<label>Description<span class="required">*</span></label>
<textarea id="projectFiscalDescription" formControlName="projectFiscalDescription" rows="4" cols="50"></textarea>
</div>
<div class="form-item half-width">
<label>Other Partners</label>
<input type="text" id="otherPartners" formControlName="otherPartners" />
<input type="text" id="otherPartner" formControlName="otherPartner" />
</div>
<!-- Budget Section -->
<div class="budget-section">
Expand All @@ -122,7 +140,8 @@

<div class="form-item budget-width">
<label>Forecast Amount</label>
<input type="Cost" id="" />
<input type="Cost" id="fiscalForecastAmount"
formControlName="fiscalForecastAmount"/>
</div>

<div class="form-item budget-width">
Expand All @@ -134,7 +153,7 @@
<label>Ancilliary Funding Provider</label>
<select id="ancillaryFundingSourceGuid" formControlName="ancillaryFundingSourceGuid">
<option value="" >Select</option>
<option *ngFor="let item of ancillaryFundingSourceCode"[value]="item.fundingSourceAbbreviation">
<option *ngFor="let item of ancillaryFundingSourceCode"[value]="item.ancillaryFundingSourceGuid">
{{ item.fundingSourceName || 'Select' }}
</option>
</select>
Expand All @@ -152,13 +171,13 @@

<div class="form-item cfs-width">
<label>CFS Actual Spend</label>
<input type="Cost" id=""/>
<input type="Cost" id="fiscalActualAmount" formControlName="fiscalActualAmount"/>
</div>
</form>
<div class="fiscal-footer">
<div class="footer-button-row">
<button class="secondary" (click)="onCancelFiscal()" >Cancel</button>
<button type="button" (click)="onSaveFiscal(i)"
<button class="secondary" (click)="onCancelFiscal()" [disabled]="!fiscalForms[i].dirty" >Cancel</button>
<button type="button" (click)="onSaveFiscal(i)" [disabled]="!fiscalForms[i].valid || !fiscalForms[i].dirty"
class="primary">Save
</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,39 @@
}
}
}
}
}

.header-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.dropdown-button{
color: #FFF;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: normal;
margin-right: 40px;
background-color: var(--wf-primary-color);
border-radius: 0;
width: auto;
border-radius: 10px;
height: 35px;
span{
padding-right: 10px;
vertical-align: top;
}
}

.action-icon{
width: 14px;
height: 14px;
}
}

.new-fiscal-button {
font-size: 12px !important;
font-weight: 400 !important;
font-family: var(--wf-font-family-main);
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,168 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ProjectFiscalsComponent } from './project-fiscals.component';
import { ActivatedRoute } from '@angular/router';
import { of, throwError } from 'rxjs';
import { ProjectService } from 'src/app/services/project-services';
import { CodeTableServices } from 'src/app/services/code-table-services';
import { MatSnackBar } from '@angular/material/snack-bar';
import { FormBuilder } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

const mockProjectService = {
getProjectFiscalsByProjectGuid: jasmine.createSpy('getProjectFiscalsByProjectGuid').and.returnValue(
of({ _embedded: { projectFiscals: [{ fiscalYear: 2023, projectFiscalName: 'Test Fiscal' }] } })
),
updateProjectFiscal: jasmine.createSpy('updateProjectFiscal').and.returnValue(of({})),
createProjectFiscal: jasmine.createSpy('createProjectFiscal').and.returnValue(of({})),
};

const mockCodeTableServices = {
fetchCodeTable: jasmine.createSpy('fetchCodeTable').and.returnValue(of({ _embedded: {} })),
};

const mockSnackBar = {
open: jasmine.createSpy('open'),
};

describe('ProjectFiscalsComponent', () => {
let component: ProjectFiscalsComponent;
let fixture: ComponentFixture<ProjectFiscalsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ProjectFiscalsComponent]
})
.compileComponents();
imports: [ProjectFiscalsComponent, BrowserAnimationsModule],
providers: [
{ provide: ActivatedRoute, useValue: { snapshot: { queryParamMap: { get: () => 'test-guid' } } } },
{ provide: ProjectService, useValue: mockProjectService },
{ provide: CodeTableServices, useValue: mockCodeTableServices },
{ provide: MatSnackBar, useValue: mockSnackBar },
FormBuilder,
],
}).compileComponents();

fixture = TestBed.createComponent(ProjectFiscalsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
it('should create the component', () => {
expect(component).toBeTruthy();
});

it('should generate fiscal years correctly', () => {
component.generateFiscalYears();
expect(component.fiscalYears.length).toBe(11);
expect(component.fiscalYears[0]).toBe(`${new Date().getFullYear() - 5}/${(new Date().getFullYear() - 4).toString().slice(-2)}`);
});

it('should load code tables successfully', () => {
mockCodeTableServices.fetchCodeTable.calls.reset(); // ✅ Reset call count
component.loadCodeTables();
expect(mockCodeTableServices.fetchCodeTable).toHaveBeenCalledTimes(3);
});

it('should handle errors in loading code tables', () => {
mockCodeTableServices.fetchCodeTable.calls.reset(); // ✅ Reset call count
mockCodeTableServices.fetchCodeTable.and.returnValue(throwError(() => new Error('Error fetching data')));
component.loadCodeTables();
expect(mockCodeTableServices.fetchCodeTable).toHaveBeenCalledTimes(3);
});

it('should load project fiscals', () => {
// ✅ Ensure the mock returns a valid response
mockProjectService.getProjectFiscalsByProjectGuid.and.returnValue(
of({
_embedded: {
projectFiscals: [
{ fiscalYear: 2023, projectFiscalName: 'Test Fiscal' }
]
}
})
);

component.loadProjectFiscals();

expect(mockProjectService.getProjectFiscalsByProjectGuid).toHaveBeenCalledWith('test-guid');
expect(component.projectFiscals.length).toBeGreaterThan(0); // ✅ Should now have at least one fiscal
expect(component.fiscalForms.length).toBe(component.projectFiscals.length); // ✅ Forms should match project fiscals count
});


it('should handle errors in loading project fiscals', () => {
mockProjectService.getProjectFiscalsByProjectGuid.and.returnValue(throwError(() => new Error('API Error')));
component.loadProjectFiscals();
expect(component.projectFiscals.length).toBe(0);
});

it('should add a new fiscal', () => {
component.projectFiscals = []; // ✅ Ensure projectFiscals starts empty
component.projectGuid = 'test-guid'; // ✅ Ensure projectGuid is set before calling the method

component.addNewFiscal();

expect(component.projectFiscals.length).toBe(1); // ✅ Should increase from 0 to 1
expect(component.selectedTabIndex).toBe(0); // ✅ Should select the first added fiscal
});

it('should save a new fiscal', () => {
spyOn(component, 'loadProjectFiscals');

// Ensure mock `createProjectFiscal` returns success
mockProjectService.createProjectFiscal.and.returnValue(of({})); // ✅ Fix: Return success response

component.onSaveFiscal(0);

expect(mockProjectService.createProjectFiscal).toHaveBeenCalled();
expect(mockSnackBar.open).toHaveBeenCalledWith(
component.messages.projectFiscalCreatedSuccess,
'OK',
{ duration: 5000, panelClass: 'snackbar-success' } // ✅ Ensure correct snackbar message
);
expect(component.loadProjectFiscals).toHaveBeenCalled();
});

it('should handle errors when saving a new fiscal', () => {
mockProjectService.createProjectFiscal.and.returnValue(throwError(() => new Error('API Error')));
component.onSaveFiscal(0);
expect(mockSnackBar.open).toHaveBeenCalledWith(component.messages.projectFiscalCreatedFailure, 'OK', {
duration: 5000,
panelClass: 'snackbar-error',
});
});

it('should update an existing fiscal', () => {
spyOn(component, 'loadProjectFiscals');

// ✅ Ensure updateProjectFiscal returns success
mockProjectService.updateProjectFiscal.and.returnValue(of({}));

component.projectFiscals = [{ projectPlanFiscalGuid: 'existing-guid' }]; // ✅ Ensure a valid fiscal object exists

component.onSaveFiscal(0);

expect(mockProjectService.updateProjectFiscal).toHaveBeenCalled();
expect(mockSnackBar.open).toHaveBeenCalledWith(
component.messages.projectFiscalUpdatedSuccess,
'OK',
{ duration: 5000, panelClass: 'snackbar-success' } // ✅ Ensure correct success message
);
expect(component.loadProjectFiscals).toHaveBeenCalled();
});


it('should handle errors when updating an existing fiscal', () => {
// ✅ Ensure projectFiscals is initialized before setting properties
component.projectFiscals = [{ projectPlanFiscalGuid: 'existing-guid' }];

mockProjectService.updateProjectFiscal.and.returnValue(throwError(() => new Error('API Error')));

component.onSaveFiscal(0);

expect(mockSnackBar.open).toHaveBeenCalledWith(
component.messages.projectFiscalUpdatedFailure,
'OK',
{ duration: 5000, panelClass: 'snackbar-error' } // ✅ Ensure correct error message is tested
);
});

});
Loading

0 comments on commit a261e27

Please sign in to comment.