Commit 32728447 authored by Sabino's avatar Sabino

Tests added

parent 003982a2
...@@ -2,3 +2,4 @@ ...@@ -2,3 +2,4 @@
node_modules node_modules
dist dist
build build
coverage
\ No newline at end of file
/* tslint:disable:no-unused-variable */ /* tslint:disable:no-unused-variable */
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('App', () => {
beforeEach(function() {
this.app = new AppComponent();
});
it('should create the app', function() {
expect(this.app).toBeTruthy();
});
});
/*
import { TestBed, async } from '@angular/core/testing'; import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { FromUnixPipe, DateFormatPipe } from 'angular2-moment';
import { CapitalizePipe } from './pipes/capitalize.pipe';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { APP_BASE_HREF } from '@angular/common';
import { routing, ZoeRoutingProviders } from './app-routing.module';
import { NavbarComponent } from './components/navbar/navbar.component';
import { LoginComponent } from './components/login/login.component';
import { ExecutionInfoComponent } from './components/execution-info/execution-info.component';
import { ExecutionNewComponent } from './components/execution-new/execution-new.component';
import { ExecutionListComponent } from './components/execution-list/execution-list.component';
import { ApiService } from './services/api.service';
import { StorageService } from './services/storage.service';
import { ActivatedRoute } from '@angular/router';
let fixture;
describe('App: Zoe', () => { describe('App: Zoe', () => {
let apiServiceStub = {
getAllExecutions: () => executions
};
let storageServiceStub = {
getUsername: () => "admin"
};
let activateRouteStub = {
params: [{"id":100}]
};
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ declarations: [
AppComponent AppComponent,
LoginComponent,
NavbarComponent,
ExecutionInfoComponent,
ExecutionNewComponent,
ExecutionListComponent,
CapitalizePipe,
FromUnixPipe,
DateFormatPipe
],
imports: [
FormsModule,
ReactiveFormsModule,
HttpModule,
routing
],
providers: [
{provide: ActivatedRoute, useValue: activateRouteStub },
{provide: ApiService, useValue: apiServiceStub },
{provide: StorageService, useValue: storageServiceStub },
ApiService,
StorageService,
ZoeRoutingProviders,
{provide: APP_BASE_HREF, useValue : '/' }
], ],
bootstrap: [
AppComponent
]
}); });
fixture = TestBed.createComponent(AppComponent);
}); });
it('should create the app', async(() => { it('should create the app', async(() => {
let fixture = TestBed.createComponent(AppComponent);
let app = fixture.debugElement.componentInstance; let app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy(); expect(app).toBeTruthy();
})); }));
it(`should have as title 'Zoe - Dashboard'`, async(() => { it(`should have as title 'Zoe - Dashboard'`, async(() => {
let fixture = TestBed.createComponent(AppComponent);
let app = fixture.debugElement.componentInstance; let app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('Zoe - Dashboard'); expect(app.title).toEqual('Zoe - Dashboard');
})); }));
it('should render the navbar', async(() => { it('should render the navbar', async(() => {
let fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement; let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('nav a.navbar-brand').textContent).toContain('Zoe'); expect(compiled.querySelector('nav a.navbar-brand').textContent).toContain('Zoe');
...@@ -38,3 +108,4 @@ describe('App: Zoe', () => { ...@@ -38,3 +108,4 @@ describe('App: Zoe', () => {
expect(compiled.querySelector('h1').textContent).toContain('Login'); expect(compiled.querySelector('h1').textContent).toContain('Login');
})); }));
}); });
*/
\ No newline at end of file
import { Component } from '@angular/core'; import { Component } from '@angular/core';
@Component({ @Component({
selector: 'zoe', selector: 'app-zoe',
template: ` template: `
<navbar></navbar> <navbar></navbar>
......
/* tslint:disable:no-unused-variable */ /* tslint:disable:no-unused-variable */
import { TestBed, async } from '@angular/core/testing'; import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { Execution } from '../../entities/execution'
import { Service } from '../../entities/service'
import { By } from '@angular/platform-browser';
import { ExecutionInfoComponent } from './execution-info.component'; import { ExecutionInfoComponent } from './execution-info.component';
import { ApiService } from '../../services/api.service';
import { FromUnixPipe, DateFormatPipe } from 'angular2-moment';
import { CapitalizePipe } from '../../pipes/capitalize.pipe';
import { ActivatedRoute } from '@angular/router';
let comp: ExecutionInfoComponent;
let fixture: ComponentFixture<ExecutionInfoComponent>;
let spyGetExecutionDetails;
let spyGetServiceDetails;
describe('Component: ExecutionInfo', () => { describe('Component: ExecutionInfo', () => {
let executionDetails = {
'id': '123',
'name': 'Execution Test',
'owner': 'owner1234',
'status': 'running',
'services': [456]
};
let execution = new Execution().deserialize(executionDetails);
let serviceDetails = {
'id': '456',
'name': 'Service Test'
};
let service = new Service().deserialize(serviceDetails);
let activateRouteStub = {
params: [{"id":100}]
};
let apiServiceStub = {
getExecutionDetails: (id: string) => execution,
getServiceDetails: (id: string) => service
};
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
ExecutionInfoComponent,
CapitalizePipe,
FromUnixPipe,
DateFormatPipe
], // declare the test component
providers: [
{provide: ActivatedRoute, useValue: activateRouteStub },
{provide: ApiService, useValue: apiServiceStub }
]
});
fixture = TestBed.createComponent(ExecutionInfoComponent);
comp = fixture.componentInstance; // BannerComponent test instance
let apiService = TestBed.get(ApiService);
spyGetExecutionDetails = spyOn(apiService, 'getExecutionDetails')
.and.returnValue(Promise.resolve(execution));
spyGetServiceDetails = spyOn(apiService, 'getServiceDetails')
.and.returnValue(Promise.resolve(service));
});
it('should create an instance', () => { it('should create an instance', () => {
let component = new ExecutionInfoComponent(); expect(fixture).toBeTruthy();
expect(component).toBeTruthy(); });
it('should not show "Details" before "getExecutionDetails" call', () => {
expect(fixture.debugElement.query(By.css('#execution-details'))).toBeNull();
expect(fixture.debugElement.query(By.css('#execution-service'))).toBeNull();
expect(spyGetExecutionDetails.calls.any()).toBe(false, 'getExecutionDetails not yet called');
expect(spyGetServiceDetails.calls.any()).toBe(false, 'getServiceDetails not yet called');
}); });
});
it('should still not show quote after component initialized', () => {
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('.spinner-title')).nativeElement.textContent).toContain('Loading...');
expect(spyGetExecutionDetails.calls.any()).toBe(true, 'getExecutionDetails called');
expect(spyGetServiceDetails.calls.any()).toBe(false, 'getServiceDetails called');
});
it('should show execution details and service', async(() => {
fixture.detectChanges();
fixture.whenStable().then(() => { // wait for async getQuote
fixture.detectChanges(); // update view with quote
expect(fixture.debugElement.query(By.css('#execution-details')).nativeElement).toBeDefined();
expect(fixture.debugElement.query(By.css('#execution-service')).nativeElement).toBeDefined();
});
}));
});
\ No newline at end of file
...@@ -17,7 +17,7 @@ import { ApiService } from '../../services/api.service'; ...@@ -17,7 +17,7 @@ import { ApiService } from '../../services/api.service';
<div *ngIf="loading" class="spinner-block"> <div *ngIf="loading" class="spinner-block">
<div class="spinner-title">Loading...</div> <i class="spinner-icon"></i> <div class="spinner-title">Loading...</div> <i class="spinner-icon"></i>
</div> </div>
<div *ngIf="!loading && execution"> <div *ngIf="!loading && execution" id="execution-details">
<h1>Execution <em>{{execution.id}}</em></h1> <h1>Execution <em>{{execution.id}}</em></h1>
<hr /> <hr />
<h3>Details</h3> <h3>Details</h3>
...@@ -47,7 +47,7 @@ import { ApiService } from '../../services/api.service'; ...@@ -47,7 +47,7 @@ import { ApiService } from '../../services/api.service';
<div *ngIf="!hasServices()" class="row"> <div *ngIf="!hasServices()" class="row">
<div class="text-danger col-md-3 col-md-offset-1">No services</div> <div class="text-danger col-md-3 col-md-offset-1">No services</div>
</div> </div>
<div *ngIf="hasServices()" class="row service-list"> <div *ngIf="hasServices()" class="row service-list" id="execution-service">
<div class="col-md-6"> <div class="col-md-6">
<dl *ngFor="let service of services" class="dl-horizontal"> <dl *ngFor="let service of services" class="dl-horizontal">
<dt>Id</dt> <dt>Id</dt>
...@@ -67,12 +67,12 @@ import { ApiService } from '../../services/api.service'; ...@@ -67,12 +67,12 @@ import { ApiService } from '../../services/api.service';
` `
}) })
export class ExecutionInfoComponent implements OnInit { export class ExecutionInfoComponent implements OnInit {
private loading = true private loading = true;
private errorMessage: string private errorMessage: string;
private warningMessage: string private warningMessage: string;
private execution: Execution; private execution: Execution;
private services: Service[] private services: Service[];
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
...@@ -89,46 +89,48 @@ export class ExecutionInfoComponent implements OnInit { ...@@ -89,46 +89,48 @@ export class ExecutionInfoComponent implements OnInit {
} }
hasServices(): Boolean { hasServices(): Boolean {
return this.services && (this.services.length > 0) return this.services && (this.services.length > 0);
} }
setExecutionDetails(execution: Execution) { setExecutionDetails(execution: Execution) {
this.execution = execution this.execution = execution;
this.getServicesDetails(execution) this.getServicesDetails(execution);
} }
getServicesDetails(execution: Execution) { getServicesDetails(execution: Execution) {
if (execution.services && execution.services.length > 0) { if (execution.services && execution.services.length > 0) {
this.services = [] this.services = [];
var errors = false let errors = false;
for (let srv of execution.services) { for (let srv of execution.services) {
this.apiService.getServiceDetails(srv.toString()) this.apiService.getServiceDetails(srv.toString())
.then(service => this.services.push(service)) .then(service => this.services.push(service))
.catch(error => errors = true); .catch(error => errors = true);
} }
if (errors)
if (errors) {
this.showWarning('Failed to retrieve one or more services.'); this.showWarning('Failed to retrieve one or more services.');
}
this.hideLoading() this.hideLoading();
} }
} }
showLoading() { showLoading() {
this.loading = true this.loading = true;
} }
hideLoading() { hideLoading() {
this.loading = false this.loading = false;
} }
showError(msg: string) { showError(msg: string) {
this.hideLoading() this.hideLoading();
this.errorMessage = msg this.errorMessage = msg;
} }
showWarning(msg: string) { showWarning(msg: string) {
this.hideLoading() this.hideLoading();
this.warningMessage = msg this.warningMessage = msg;
} }
} }
/* tslint:disable:no-unused-variable */ /* tslint:disable:no-unused-variable */
import { TestBed, async } from '@angular/core/testing'; import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { Execution } from '../../entities/execution'
import { StorageService } from '../../services/storage.service';
import { ApiService } from '../../services/api.service';
import { By } from '@angular/platform-browser';
import { ExecutionListComponent } from './execution-list.component'; import { ExecutionListComponent } from './execution-list.component';
import { LoginComponent } from '../login/login.component';
import { FromUnixPipe, DateFormatPipe } from 'angular2-moment';
import { CapitalizePipe } from '../../pipes/capitalize.pipe';
import { Router } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterLinkStubDirective } from '../../testing/router-stubs';
let comp: ExecutionListComponent;
let fixture: ComponentFixture<ExecutionListComponent>;
let spyGetAllExecutions;
describe('Component: ExecutionList', () => { describe('Component: ExecutionList', () => {
let executions = [
new Execution().deserialize(
{
'id': '1',
'name': 'Execution Test',
'owner': 'admin',
'status': 'running',
'services': [1]
}
),
new Execution().deserialize(
{
'id': '2',
'name': 'Execution Test',
'owner': 'admin',
'status': 'running',
'services': [2]
}
),
new Execution().deserialize(
{
'id': '3',
'name': 'Execution Test',
'owner': 'admin',
'status': 'running',
'services': [3]
}
),
];
let routerStub = {
navigateByUrl: (url: string) => true
};
let apiServiceStub = {
getAllExecutions: () => executions,
isUserLoggedIn: () => true
};
let storageServiceStub = {
getUsername: () => "admin"
};
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
RouterLinkStubDirective,
ExecutionListComponent,
LoginComponent,
CapitalizePipe,
FromUnixPipe,
DateFormatPipe
],
imports: [
FormsModule,
ReactiveFormsModule
],
providers: [
{provide: Router, useValue: routerStub },
{provide: ApiService, useValue: apiServiceStub },
{provide: StorageService, useValue: storageServiceStub }
]
});
fixture = TestBed.createComponent(ExecutionListComponent);
comp = fixture.componentInstance; // BannerComponent test instance
let apiService = TestBed.get(ApiService);
spyGetAllExecutions = spyOn(apiService, 'getAllExecutions')
.and.returnValue(Promise.resolve(executions));
});
it('should create an instance', () => { it('should create an instance', () => {
let component = new ExecutionListComponent(); expect(fixture).toBeTruthy();
expect(component).toBeTruthy();
}); });
});
it('should not show the table before "getAllExecutions" call', () => {
expect(fixture.debugElement.query(By.css('#executions-list-table'))).toBeNull();
expect(spyGetAllExecutions.calls.any()).toBe(false, 'getAllExecutions not yet called');
});
it('should still not show quote after component initialized', () => {
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('.spinner-title')).nativeElement.textContent).toContain('Loading...');
expect(spyGetAllExecutions.calls.any()).toBe(true, 'getAllExecutions called');
});
it('should show execution list table', async(() => {
fixture.detectChanges();
fixture.whenStable().then(() => { // wait for async getQuote
fixture.detectChanges(); // update view with quote
expect(fixture.debugElement.query(By.css('#executions-list-table')).nativeElement).toBeDefined();
});
}));
});
\ No newline at end of file
/* tslint:disable:no-unused-variable */ /* tslint:disable:no-unused-variable */
import { TestBed, async } from '@angular/core/testing'; import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { ExecutionNewComponent } from './execution-new.component'; import { ExecutionNewComponent } from './execution-new.component';
import { By } from '@angular/platform-browser';
import { ApiService } from '../../services/api.service';
import { FromUnixPipe, DateFormatPipe } from 'angular2-moment';
import { CapitalizePipe } from '../../pipes/capitalize.pipe';
import { APP_BASE_HREF } from '@angular/common';
import { routing, ZoeRoutingProviders } from '../../app-routing.module';
import { Routes, RouterModule, Router } from '@angular/router';
let comp: ExecutionNewComponent;
let fixture: ComponentFixture<ExecutionNewComponent>;
describe('Component: ExecutionNew', () => { describe('Component: ExecutionNew', () => {
let apiServiceStub = {
startExecution: (name: string, application: Object) => 1
};
let routerStub = {
navigateByUrl: (url: string) => true
}
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
ExecutionNewComponent,
CapitalizePipe,
FromUnixPipe,
DateFormatPipe
], // declare the test component
providers: [
{provide: Router, useValue: routerStub },
{provide: ApiService, useValue: apiServiceStub },
ZoeRoutingProviders,
{provide: APP_BASE_HREF, useValue : '/' }
]
});
fixture = TestBed.createComponent(ExecutionNewComponent);
comp = fixture.componentInstance; // BannerComponent test instance
let apiService = TestBed.get(ApiService);
});
it('should create an instance', () => { it('should create an instance', () => {
let component = new ExecutionNewComponent(); expect(fixture).toBeTruthy();
expect(component).toBeTruthy();
}); });
it('should have "Name" input field', () => { it('should have "Name" input field', () => {
let component = new ExecutionNewComponent(); expect(fixture.debugElement.query(By.css('label[for="inputName"]')).nativeElement.textContent).toContain('Name');
let compiled = component.debugElement.nativeElement;
expect(compiled.querySelector('label[for="inputName"]').textContent).toContain('Name');
}); });
it('should have "Description" input field', () => { it('should have "Description" input field', () => {
let component = new ExecutionNewComponent(); expect(fixture.debugElement.query(By.css('label[for="inputDescription"]')).nativeElement.textContent).toContain('Description');
let compiled = component.debugElement.nativeElement;
expect(compiled.querySelector('label[for="inputDescription"]').textContent).toContain('Description');
}); });
it('should have "Submit" button', () => { it('should have "Submit" button', () => {
let component = new ExecutionNewComponent(); expect(fixture.debugElement.query(By.css('button[type="submit"]')).nativeElement.textContent).toContain('Submit');
let compiled = component.debugElement.nativeElement;
expect(compiled.querySelector('button[type="submit"]').textContent).toContain('Submit');
}); });
}); });
/* tslint:disable:no-unused-variable */ /* tslint:disable:no-unused-variable */
import { TestBed, async } from '@angular/core/testing'; import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { LoginComponent } from './login.component'; import { LoginComponent } from './login.component';
import { By } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ApiService } from '../../services/api.service';
import { FromUnixPipe, DateFormatPipe } from 'angular2-moment';
import { CapitalizePipe } from '../../pipes/capitalize.pipe';
import { Router } from '@angular/router';
import { RouterLinkStubDirective } from '../../testing/router-stubs';
let comp: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
//let de: DebugElement;
//let el: HTMLElement;
describe('Component: Login', () => { describe('Component: Login', () => {
let routerStub = {
navigateByUrl: (url: string) => true
};
let apiServiceStub = {
isUserLoggedIn: () => false,
login: (username: string, password: string) => true
};
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
RouterLinkStubDirective,
LoginComponent,
CapitalizePipe,
FromUnixPipe,
DateFormatPipe
], // declare the test component
imports: [
FormsModule,
ReactiveFormsModule
],
providers: [
{provide: Router, useValue: routerStub },
{provide: ApiService, useValue: apiServiceStub }
]
});
fixture = TestBed.createComponent(LoginComponent);
comp = fixture.componentInstance; // BannerComponent test instance
});
it('should create an instance', () => { it('should create an instance', () => {
let component = new LoginComponent(); expect(fixture).toBeTruthy();
expect(component).toBeTruthy();
}); });
it('should have title "Login"', () => { it('should have title "Login"', () => {
let component = new LoginComponent(); expect(fixture.debugElement.query(By.css('h1')).nativeElement.textContent).toContain('Login');
expect(component).toBeTruthy();
let compiled = component.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Login');
}); });
it('should have "Username" input field', () => { it('should have "Username" input field', () => {
let component = new LoginComponent(); expect(fixture.debugElement.query(By.css('label[for="inputUsername"]')).nativeElement.textContent).toContain