Skip to content

Commit 9b86107

Browse files
committed
Merge branch 'master' of https://github.com/ioet/time-tracker-ui into Time-Clock-Timer-Component
2 parents f9aa410 + 85dbadd commit 9b86107

File tree

9 files changed

+236
-16
lines changed

9 files changed

+236
-16
lines changed

.github/workflows/master_time-tracker-ui.yml renamed to .github/workflows/CD-time-tracker-ui.yml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
11
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
22
# More GitHub Actions for Azure: https://github.com/Azure/actions
33

4-
name: Build and deploy Node.js app to Azure Web App - time-tracker-ui
4+
name: CD process to deploy to App-Service service
55

66
on:
7-
push:
7+
# Trigger the workflow on pull request but only for the master branch
8+
pull_request:
9+
types: [closed]
810
branches:
911
- master
1012

1113
jobs:
1214
build-and-deploy:
15+
name: Deploy to Azure
1316
runs-on: ubuntu-latest
14-
17+
timeout-minutes: 60
1518
steps:
16-
- uses: actions/checkout@master
19+
- name: Checkout of master
20+
uses: actions/checkout@master
1721

1822
- name: Set up Node.js version
1923
uses: actions/setup-node@v1
2024
with:
2125
node-version: '12.x'
2226

23-
- name: npm install, build, and test
27+
- name: 'run: npm install and build'
2428
run: |
2529
npm install
26-
npm run build --if-present
27-
# npm run test --if-present
30+
npm run build --prod --if-present
2831
2932
- name: 'Deploy to Azure Web App'
3033
uses: azure/webapps-deploy@v1
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: CI process for time-tracker app
2+
3+
on:
4+
# Trigger the workflow on push or pull request
5+
push:
6+
branches:
7+
- '*'
8+
- '*/*'
9+
- '!master'
10+
11+
pull_request:
12+
types: [opened, edited, reopened, synchronize]
13+
branches:
14+
- master
15+
16+
jobs:
17+
security-audit:
18+
name: Running npm audit
19+
runs-on: ubuntu-latest
20+
timeout-minutes: 60
21+
steps:
22+
- name: Clone and checkout branch
23+
uses: actions/checkout@master
24+
25+
- name: Set up Node.js version
26+
uses: actions/setup-node@v1
27+
with:
28+
node-version: '12.x'
29+
30+
- name: Security Audit
31+
run: npm audit --audit-level=moderate
32+
33+
ci-test:
34+
name: Running unit tests
35+
runs-on: ubuntu-latest
36+
timeout-minutes: 90
37+
steps:
38+
- name: Clone and checkout branch
39+
uses: actions/checkout@master
40+
41+
- name: Set up Node.js version
42+
uses: actions/setup-node@v1
43+
with:
44+
node-version: '12.x'
45+
46+
- name: Install dependencies
47+
run: npm install
48+
49+
- name: Run the test
50+
run: npm run ci-test --if-present

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"start": "ng serve",
77
"build": "ng build",
88
"test": "ng test",
9+
"ci-test": "ng test --no-watch --no-progress --browsers ChromeHeadless",
910
"lint": "ng lint",
1011
"e2e": "ng e2e"
1112
},

src/app/components/options-sidebar/project-management/project-management.component.spec.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
2-
32
import { ProjectManagementComponent } from './project-management.component';
43
import { Project } from '../../../interfaces/project';
54
import { ProjectService } from '../../../services/project.service';
65
import { of } from 'rxjs';
6+
import { CreateProjectComponent } from '../../../components/shared/create-project/create-project.component';
7+
import { ProjectListComponent } from '../../../components/shared/project-list/project-list.component';
8+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
79

810
describe('ProjectManagementComponent', () => {
911
let component: ProjectManagementComponent;
@@ -42,8 +44,12 @@ describe('ProjectManagementComponent', () => {
4244

4345
beforeEach(async(() => {
4446
TestBed.configureTestingModule({
45-
declarations: [ ProjectManagementComponent ],
46-
providers: [ { provide: ProjectService, useValue: projectServiceStub }]
47+
declarations: [ ProjectManagementComponent, CreateProjectComponent, ProjectListComponent ],
48+
providers: [ { provide: ProjectService, useValue: projectServiceStub }],
49+
imports: [
50+
FormsModule,
51+
ReactiveFormsModule
52+
]
4753
})
4854
.compileComponents();
4955
}));

src/app/components/options-sidebar/project-management/project-management.component.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export class ProjectManagementComponent implements OnInit {
3535
};
3636
this.projects = this.projects.concat(newProject);
3737
}
38-
console.log(this.projects);
3938
}
4039

4140
editProject(projectId) {

src/app/components/shared/create-project/create-project.component.spec.ts

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
22

33
import { CreateProjectComponent } from './create-project.component';
44
import { Validators, FormBuilder } from '@angular/forms';
5+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
56

67
describe('CreateProjectComponent', () => {
78
let component: CreateProjectComponent;
@@ -10,9 +11,10 @@ describe('CreateProjectComponent', () => {
1011
beforeEach(async(() => {
1112
TestBed.configureTestingModule({
1213
declarations: [ CreateProjectComponent ],
13-
providers: [
14-
FormBuilder
15-
],
14+
imports: [
15+
FormsModule,
16+
ReactiveFormsModule
17+
]
1618
})
1719
.compileComponents();
1820
}));
@@ -26,4 +28,74 @@ describe('CreateProjectComponent', () => {
2628
it('should create', () => {
2729
expect(component).toBeTruthy();
2830
});
31+
32+
it('should send the form data on onSubmit buton #onSubmit', () => {
33+
const project = {
34+
name: 'app 4',
35+
details: 'It is a good app',
36+
status: 'inactive',
37+
completed: true
38+
};
39+
40+
spyOn(component.savedProject, 'emit');
41+
component.onSubmit(project);
42+
expect(component.savedProject.emit).toHaveBeenCalled();
43+
});
44+
45+
it('should clean the form and send a cancelForm event #reset', () => {
46+
const project = {
47+
name: 'app 4',
48+
details: 'It is a good app',
49+
status: 'inactive',
50+
completed: true
51+
};
52+
53+
component.projectForm.setValue(project);
54+
spyOn(component.cancelForm, 'emit');
55+
component.reset();
56+
expect(component.projectForm.value.name).toEqual(null);
57+
expect(component.projectForm.value.details).toEqual(null);
58+
expect(component.projectForm.value.status).toEqual(null);
59+
expect(component.projectForm.value.completed).toEqual(null);
60+
61+
expect(component.cancelForm.emit).toHaveBeenCalled();
62+
});
63+
64+
it('form invalid when empty', () => {
65+
expect(component.projectForm.valid).toBeFalsy();
66+
});
67+
68+
it('name field validity', () => {
69+
const name = component.projectForm.controls.name;
70+
expect(name.valid).toBeFalsy();
71+
72+
name.setValue('');
73+
expect(name.hasError('required')).toBeTruthy();
74+
75+
name.setValue('A');
76+
expect(name.hasError('required')).toBeFalsy();
77+
});
78+
79+
it('details field validity', () => {
80+
const details = component.projectForm.controls.details;
81+
expect(details.valid).toBeFalsy();
82+
83+
details.setValue('');
84+
expect(details.hasError('required')).toBeTruthy();
85+
86+
details.setValue('A');
87+
expect(details.hasError('required')).toBeFalsy();
88+
});
89+
90+
it('status field validity', () => {
91+
const status = component.projectForm.controls.status;
92+
expect(status.valid).toBeFalsy();
93+
94+
status.setValue('');
95+
expect(status.hasError('required')).toBeTruthy();
96+
97+
status.setValue('A');
98+
expect(status.hasError('required')).toBeFalsy();
99+
});
100+
29101
});

src/app/components/shared/modal/modal.component.spec.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,22 @@ describe('ModalComponent', () => {
2222
it('should create', () => {
2323
expect(component).toBeTruthy();
2424
});
25+
26+
it('should emit removeProject event #removedProject', () => {
27+
const project = {
28+
id: 1,
29+
name: 'app 4',
30+
details: 'It is a good app',
31+
status: 'inactive',
32+
completed: true
33+
};
34+
35+
spyOn(component.removeProject, 'emit');
36+
component.project = project;
37+
fixture.detectChanges();
38+
component.removedProject(project.id);
39+
expect(component.removeProject.emit).toHaveBeenCalled();
40+
component.cancelDeleteModal.nativeElement.click();
41+
});
2542
});
43+

src/app/components/shared/project-list/project-list.component.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,37 @@ describe('ProjectListComponent', () => {
2222
it('should create', () => {
2323
expect(component).toBeTruthy();
2424
});
25+
26+
it('should emit deleteProject event #removeProject', () => {
27+
const project = {
28+
id: 1,
29+
name: 'app 4',
30+
details: 'It is a good app',
31+
status: 'inactive',
32+
completed: true
33+
};
34+
35+
component.projectToDelete = project;
36+
spyOn(component.deleteProject, 'emit');
37+
component.removeProject(project.id);
38+
expect(component.deleteProject.emit).toHaveBeenCalled();
39+
expect(component.projectToDelete).toBe(null);
40+
});
41+
42+
it('should open delete modal #openModal', () => {
43+
const project = {
44+
id: 1,
45+
name: 'app 4',
46+
details: 'It is a good app',
47+
status: 'inactive',
48+
completed: true
49+
};
50+
51+
component.openModal(project);
52+
expect(component.projectToDelete.id).toBe(1);
53+
expect(component.projectToDelete.name).toBe('app 4');
54+
expect(component.projectToDelete.details).toBe('It is a good app');
55+
expect(component.projectToDelete.status).toBe('inactive');
56+
expect(component.projectToDelete.completed).toBe(true);
57+
});
2558
});
Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,61 @@
11
import { TestBed, inject, async } from '@angular/core/testing';
2-
import { HttpClientTestingModule } from '@angular/common/http/testing';
3-
2+
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
3+
import { Project } from '../interfaces/project';
44
import { ProjectService } from './project.service';
55

66
describe('ProjectService', () => {
77
let service: ProjectService;
8+
let httpMock: HttpTestingController;
9+
10+
const projects: Project[] = [{
11+
id: 1,
12+
name: 'app 1',
13+
details: 'It is a good app',
14+
status: 'inactive',
15+
completed: true
16+
},
17+
{
18+
id: 2,
19+
name: 'app 2',
20+
details: 'It is a good app',
21+
status: 'inactive',
22+
completed: false
23+
},
24+
{
25+
id: 3,
26+
name: 'app 3',
27+
details: 'It is a good app',
28+
status: 'active',
29+
completed: true
30+
}
31+
];
832

933
beforeEach(() => {
1034
TestBed.configureTestingModule({
1135
imports: [HttpClientTestingModule]
1236
});
1337
service = TestBed.inject(ProjectService);
38+
httpMock = TestBed.inject(HttpTestingController);
1439
});
1540

41+
afterEach (() => {
42+
httpMock.verify ();
43+
});
1644

1745
it('should create', inject([HttpClientTestingModule, ProjectService],
1846
(httpClient: HttpClientTestingModule, apiService: ProjectService) => {
1947
expect(apiService).toBeTruthy();
2048
expect(httpClient).toBeTruthy();
2149
}));
2250

51+
it('should get projects API/GET #getProjects', () => {
52+
service.getProjects().subscribe(projects => {
53+
expect(projects.length).toBe(3);
54+
expect(projects).toEqual(projects);
55+
});
56+
const request = httpMock.expectOne('assets/project.json');
57+
expect(request.request.method).toBe('GET');
58+
request.flush(projects);
59+
});
60+
2361
});

0 commit comments

Comments
 (0)