finished tests
This commit is contained in:
		@@ -22,7 +22,7 @@
 | 
				
			|||||||
            "main": "src/main.ts",
 | 
					            "main": "src/main.ts",
 | 
				
			||||||
            "polyfills": "src/polyfills.ts",
 | 
					            "polyfills": "src/polyfills.ts",
 | 
				
			||||||
            "tsConfig": "tsconfig.app.json",
 | 
					            "tsConfig": "tsconfig.app.json",
 | 
				
			||||||
            "aot": false,
 | 
					            "aot": true,
 | 
				
			||||||
            "assets": [
 | 
					            "assets": [
 | 
				
			||||||
              "src/favicon.ico",
 | 
					              "src/favicon.ico",
 | 
				
			||||||
              "src/assets",
 | 
					              "src/assets",
 | 
				
			||||||
@@ -46,7 +46,6 @@
 | 
				
			|||||||
              "sourceMap": false,
 | 
					              "sourceMap": false,
 | 
				
			||||||
              "extractCss": true,
 | 
					              "extractCss": true,
 | 
				
			||||||
              "namedChunks": false,
 | 
					              "namedChunks": false,
 | 
				
			||||||
              "aot": true,
 | 
					 | 
				
			||||||
              "extractLicenses": true,
 | 
					              "extractLicenses": true,
 | 
				
			||||||
              "vendorChunk": false,
 | 
					              "vendorChunk": false,
 | 
				
			||||||
              "buildOptimizer": true,
 | 
					              "buildOptimizer": true,
 | 
				
			||||||
@@ -90,7 +89,6 @@
 | 
				
			|||||||
            "polyfills": "src/polyfills.ts",
 | 
					            "polyfills": "src/polyfills.ts",
 | 
				
			||||||
            "tsConfig": "tsconfig.spec.json",
 | 
					            "tsConfig": "tsconfig.spec.json",
 | 
				
			||||||
            "karmaConfig": "karma.conf.js",
 | 
					            "karmaConfig": "karma.conf.js",
 | 
				
			||||||
            "codeCoverage": true,
 | 
					 | 
				
			||||||
            "assets": [
 | 
					            "assets": [
 | 
				
			||||||
              "src/favicon.ico",
 | 
					              "src/favicon.ico",
 | 
				
			||||||
              "src/assets"
 | 
					              "src/assets"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4570
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4570
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										34
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								package.json
									
									
									
									
									
								
							@@ -12,31 +12,31 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "private": true,
 | 
					  "private": true,
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@angular/animations": "~8.2.14",
 | 
					    "@angular/animations": "~9.1.7",
 | 
				
			||||||
    "@angular/common": "~8.2.14",
 | 
					    "@angular/common": "~9.1.7",
 | 
				
			||||||
    "@angular/compiler": "~8.2.14",
 | 
					    "@angular/compiler": "~9.1.7",
 | 
				
			||||||
    "@angular/core": "~8.2.14",
 | 
					    "@angular/core": "~9.1.7",
 | 
				
			||||||
    "@angular/forms": "~8.2.14",
 | 
					    "@angular/forms": "~9.1.7",
 | 
				
			||||||
    "@angular/platform-browser": "~8.2.14",
 | 
					    "@angular/platform-browser": "~9.1.7",
 | 
				
			||||||
    "@angular/platform-browser-dynamic": "~8.2.14",
 | 
					    "@angular/platform-browser-dynamic": "~9.1.7",
 | 
				
			||||||
    "@angular/router": "~8.2.14",
 | 
					    "@angular/router": "~9.1.7",
 | 
				
			||||||
    "@hapi/joi": "^17.1.1",
 | 
					    "@hapi/joi": "^17.1.1",
 | 
				
			||||||
    "@inst-iot/bosch-angular-ui-components": "^0.5.30",
 | 
					    "@inst-iot/bosch-angular-ui-components": "^0.5.30",
 | 
				
			||||||
    "angular-2-local-storage": "^3.0.2",
 | 
					    "angular-2-local-storage": "^3.0.2",
 | 
				
			||||||
    "flatpickr": "^4.6.3",
 | 
					    "flatpickr": "^4.6.3",
 | 
				
			||||||
    "rxjs": "~6.4.0",
 | 
					    "rxjs": "~6.5.5",
 | 
				
			||||||
    "tslib": "^1.10.0",
 | 
					    "tslib": "^1.10.0",
 | 
				
			||||||
    "zone.js": "~0.9.1"
 | 
					    "zone.js": "~0.10.2"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@angular-devkit/build-angular": "^0.803.26",
 | 
					    "@angular-devkit/build-angular": "~0.901.6",
 | 
				
			||||||
    "@angular/cli": "~8.3.26",
 | 
					    "@angular/cli": "~9.1.6",
 | 
				
			||||||
    "@angular/compiler-cli": "~8.2.14",
 | 
					    "@angular/compiler-cli": "~9.1.7",
 | 
				
			||||||
    "@angular/language-service": "~8.2.14",
 | 
					    "@angular/language-service": "~9.1.7",
 | 
				
			||||||
    "@types/jasmine": "~3.3.8",
 | 
					    "@types/jasmine": "~3.3.8",
 | 
				
			||||||
    "@types/jasminewd2": "~2.0.3",
 | 
					    "@types/jasminewd2": "~2.0.3",
 | 
				
			||||||
    "@types/node": "~8.9.4",
 | 
					    "@types/node": "^12.11.1",
 | 
				
			||||||
    "codelyzer": "^5.0.0",
 | 
					    "codelyzer": "^5.1.2",
 | 
				
			||||||
    "jasmine-core": "~3.4.0",
 | 
					    "jasmine-core": "~3.4.0",
 | 
				
			||||||
    "jasmine-spec-reporter": "~4.2.1",
 | 
					    "jasmine-spec-reporter": "~4.2.1",
 | 
				
			||||||
    "karma": "~4.1.0",
 | 
					    "karma": "~4.1.0",
 | 
				
			||||||
@@ -47,6 +47,6 @@
 | 
				
			|||||||
    "protractor": "~5.4.0",
 | 
					    "protractor": "~5.4.0",
 | 
				
			||||||
    "ts-node": "~7.0.0",
 | 
					    "ts-node": "~7.0.0",
 | 
				
			||||||
    "tslint": "~5.15.0",
 | 
					    "tslint": "~5.15.0",
 | 
				
			||||||
    "typescript": "~3.5.3"
 | 
					    "typescript": "~3.8.3"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +1,53 @@
 | 
				
			|||||||
import { TestBed } from '@angular/core/testing';
 | 
					import { TestBed } from '@angular/core/testing';
 | 
				
			||||||
 | 
					 | 
				
			||||||
import { ApiService } from './api.service';
 | 
					import { ApiService } from './api.service';
 | 
				
			||||||
 | 
					import {HttpClient} from '@angular/common/http';
 | 
				
			||||||
 | 
					import {LocalStorageService} from 'angular-2-local-storage';
 | 
				
			||||||
 | 
					import {Observable} from 'rxjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let apiService: ApiService;
 | 
				
			||||||
 | 
					let httpClientSpy: jasmine.SpyObj<HttpClient>;
 | 
				
			||||||
 | 
					let localStorageServiceSpy: jasmine.SpyObj<LocalStorageService>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('ApiService', () => {
 | 
					describe('ApiService', () => {
 | 
				
			||||||
  beforeEach(() => TestBed.configureTestingModule({
 | 
					  beforeEach(() => {
 | 
				
			||||||
    providers: [ApiService, HttpClient]
 | 
					    const httpSpy = jasmine.createSpyObj('HttpClient', ['get']);
 | 
				
			||||||
  }));
 | 
					    const localStorageSpy = jasmine.createSpyObj('LocalStorageService', ['get']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TestBed.configureTestingModule({
 | 
				
			||||||
 | 
					      providers: [
 | 
				
			||||||
 | 
					        ApiService,
 | 
				
			||||||
 | 
					        {provide: HttpClient, useValue: httpSpy},
 | 
				
			||||||
 | 
					        {provide: LocalStorageService, useValue: localStorageSpy}
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    apiService = TestBed.inject(ApiService);
 | 
				
			||||||
 | 
					    httpClientSpy = TestBed.inject(HttpClient) as jasmine.SpyObj<HttpClient>;
 | 
				
			||||||
 | 
					    localStorageServiceSpy = TestBed.inject(LocalStorageService) as jasmine.SpyObj<LocalStorageService>;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('should be created', () => {
 | 
					  it('should be created', () => {
 | 
				
			||||||
    const service: ApiService = TestBed.inject(ApiService);
 | 
					    expect(apiService).toBeTruthy();
 | 
				
			||||||
    expect(service).toBeTruthy();
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should do get requests without auth if not available', () => {
 | 
				
			||||||
 | 
					    const getReturn = new Observable();
 | 
				
			||||||
 | 
					    httpClientSpy.get.and.returnValue(getReturn);
 | 
				
			||||||
 | 
					    localStorageServiceSpy.get.and.returnValue(undefined);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const result = apiService.get('/testurl');
 | 
				
			||||||
 | 
					    expect(result).toBe(getReturn);
 | 
				
			||||||
 | 
					    expect(httpClientSpy.get).toHaveBeenCalledWith('/testurl', {});
 | 
				
			||||||
 | 
					    expect(localStorageServiceSpy.get).toHaveBeenCalledWith('basicAuth');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  it('should do get requests with basic auth if available', () => {
 | 
				
			||||||
 | 
					    const getReturn = new Observable();
 | 
				
			||||||
 | 
					    httpClientSpy.get.and.returnValue(getReturn);
 | 
				
			||||||
 | 
					    localStorageServiceSpy.get.and.returnValue('basicAuth');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const result = apiService.get('/testurl');
 | 
				
			||||||
 | 
					    expect(result).toBe(getReturn);
 | 
				
			||||||
 | 
					    expect(httpClientSpy.get).toHaveBeenCalledWith('/testurl', jasmine.any(Object));  // could not test http headers better
 | 
				
			||||||
 | 
					    expect(localStorageServiceSpy.get).toHaveBeenCalledWith('basicAuth');
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,10 +2,12 @@ import { NgModule } from '@angular/core';
 | 
				
			|||||||
import { Routes, RouterModule } from '@angular/router';
 | 
					import { Routes, RouterModule } from '@angular/router';
 | 
				
			||||||
import {HomeComponent} from './home/home.component';
 | 
					import {HomeComponent} from './home/home.component';
 | 
				
			||||||
import {LoginService} from './login.service';
 | 
					import {LoginService} from './login.service';
 | 
				
			||||||
 | 
					import {SamplesComponent} from './samples/samples.component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const routes: Routes = [
 | 
					const routes: Routes = [
 | 
				
			||||||
  {path: '', component: HomeComponent},
 | 
					  {path: '', component: HomeComponent},
 | 
				
			||||||
 | 
					  {path: 'samples', component: SamplesComponent},
 | 
				
			||||||
  {path: 'replace-me', component: HomeComponent, canActivate: [LoginService]},
 | 
					  {path: 'replace-me', component: HomeComponent, canActivate: [LoginService]},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // if not authenticated
 | 
					  // if not authenticated
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
<rb-full-header>
 | 
					<rb-full-header>
 | 
				
			||||||
  <nav *rbMainNavItems>
 | 
					  <nav *rbMainNavItems>
 | 
				
			||||||
    <a routerLink="/" routerLinkActive="active" rbLoadingLink>Home</a>
 | 
					    <a routerLink="/" routerLinkActive="active" rbLoadingLink>Home</a>
 | 
				
			||||||
 | 
					    <a routerLink="/samples" routerLinkActive="active" rbLoadingLink>Samples</a>
 | 
				
			||||||
  </nav>
 | 
					  </nav>
 | 
				
			||||||
  <div *rbSubBrandHeader>Digital Fingerprint of Plastics</div>
 | 
					  <div *rbSubBrandHeader>Digital Fingerprint of Plastics</div>
 | 
				
			||||||
</rb-full-header>
 | 
					</rb-full-header>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,30 +1,45 @@
 | 
				
			|||||||
import { TestBed, async } from '@angular/core/testing';
 | 
					import {TestBed, async, ComponentFixture} from '@angular/core/testing';
 | 
				
			||||||
import { RouterTestingModule } from '@angular/router/testing';
 | 
					 | 
				
			||||||
import { AppComponent } from './app.component';
 | 
					import { AppComponent } from './app.component';
 | 
				
			||||||
import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
 | 
					import {By} from '@angular/platform-browser';
 | 
				
			||||||
 | 
					import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
 | 
				
			||||||
 | 
					import {RouterTestingModule} from '@angular/router/testing';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('AppComponent', () => {
 | 
					describe('AppComponent', () => {
 | 
				
			||||||
 | 
					  let component: AppComponent;
 | 
				
			||||||
 | 
					  let fixture: ComponentFixture<AppComponent>;
 | 
				
			||||||
 | 
					  let css;   // get native element by css selector
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  beforeEach(async(() => {
 | 
					  beforeEach(async(() => {
 | 
				
			||||||
    TestBed.configureTestingModule({
 | 
					    TestBed.configureTestingModule({
 | 
				
			||||||
 | 
					      declarations: [ AppComponent ],
 | 
				
			||||||
      imports: [
 | 
					      imports: [
 | 
				
			||||||
 | 
					        RbUiComponentsModule,
 | 
				
			||||||
        RouterTestingModule
 | 
					        RouterTestingModule
 | 
				
			||||||
      ],
 | 
					      ]
 | 
				
			||||||
      declarations: [
 | 
					 | 
				
			||||||
        AppComponent
 | 
					 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
 | 
					 | 
				
			||||||
    }).compileComponents();
 | 
					    }).compileComponents();
 | 
				
			||||||
  }));
 | 
					  }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('should create the app', () => {
 | 
					  beforeEach(() => {
 | 
				
			||||||
    const fixture = TestBed.createComponent(AppComponent);
 | 
					    fixture = TestBed.createComponent(AppComponent);
 | 
				
			||||||
    const app = fixture.debugElement.componentInstance;
 | 
					    component = fixture.componentInstance;
 | 
				
			||||||
    expect(app).toBeTruthy();
 | 
					    fixture.detectChanges();
 | 
				
			||||||
 | 
					    css = (selector) => fixture.debugElement.query(By.css(selector)).nativeElement;
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it(`should have the correct title'`, () => {
 | 
					  it('should create the app', () => {
 | 
				
			||||||
    const fixture = TestBed.createComponent(AppComponent);
 | 
					    expect(component).toBeTruthy();
 | 
				
			||||||
    const app = fixture.debugElement.componentInstance;
 | 
					 | 
				
			||||||
    expect(app.title).toEqual('UI');
 | 
					 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should have the header', () => {
 | 
				
			||||||
 | 
					    expect(css('rb-full-header')).toBeTruthy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should have the correct app title', () => {
 | 
				
			||||||
 | 
					    expect(css('rb-full-header div.sub-brand-content > div').innerText).toBe('Digital Fingerprint of Plastics');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should have the page container', () => {
 | 
				
			||||||
 | 
					    expect(css('.container')).toBeTruthy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,5 +6,4 @@ import { Component } from '@angular/core';
 | 
				
			|||||||
  styleUrls: ['./app.component.scss']
 | 
					  styleUrls: ['./app.component.scss']
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class AppComponent {
 | 
					export class AppComponent {
 | 
				
			||||||
  title = 'UI';
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,12 +9,14 @@ import { HomeComponent } from './home/home.component';
 | 
				
			|||||||
import {FormsModule} from '@angular/forms';
 | 
					import {FormsModule} from '@angular/forms';
 | 
				
			||||||
import {LocalStorageModule} from 'angular-2-local-storage';
 | 
					import {LocalStorageModule} from 'angular-2-local-storage';
 | 
				
			||||||
import {HttpClientModule} from '@angular/common/http';
 | 
					import {HttpClientModule} from '@angular/common/http';
 | 
				
			||||||
 | 
					import { SamplesComponent } from './samples/samples.component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@NgModule({
 | 
					@NgModule({
 | 
				
			||||||
  declarations: [
 | 
					  declarations: [
 | 
				
			||||||
    AppComponent,
 | 
					    AppComponent,
 | 
				
			||||||
    LoginComponent,
 | 
					    LoginComponent,
 | 
				
			||||||
    HomeComponent
 | 
					    HomeComponent,
 | 
				
			||||||
 | 
					    SamplesComponent
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  imports: [
 | 
					  imports: [
 | 
				
			||||||
    LocalStorageModule.forRoot({
 | 
					    LocalStorageModule.forRoot({
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,10 @@
 | 
				
			|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 | 
					import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 | 
				
			||||||
 | 
					 | 
				
			||||||
import { HomeComponent } from './home.component';
 | 
					import { HomeComponent } from './home.component';
 | 
				
			||||||
 | 
					import {Component} from '@angular/core';
 | 
				
			||||||
 | 
					import {By} from '@angular/platform-browser';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Component({selector: 'app-login', template: ''})
 | 
				
			||||||
 | 
					class LoginStubComponent {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('HomeComponent', () => {
 | 
					describe('HomeComponent', () => {
 | 
				
			||||||
  let component: HomeComponent;
 | 
					  let component: HomeComponent;
 | 
				
			||||||
@@ -8,7 +12,10 @@ describe('HomeComponent', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  beforeEach(async(() => {
 | 
					  beforeEach(async(() => {
 | 
				
			||||||
    TestBed.configureTestingModule({
 | 
					    TestBed.configureTestingModule({
 | 
				
			||||||
      declarations: [ HomeComponent ]
 | 
					      declarations: [
 | 
				
			||||||
 | 
					        HomeComponent,
 | 
				
			||||||
 | 
					        LoginStubComponent
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    .compileComponents();
 | 
					    .compileComponents();
 | 
				
			||||||
  }));
 | 
					  }));
 | 
				
			||||||
@@ -22,4 +29,8 @@ describe('HomeComponent', () => {
 | 
				
			|||||||
  it('should create', () => {
 | 
					  it('should create', () => {
 | 
				
			||||||
    expect(component).toBeTruthy();
 | 
					    expect(component).toBeTruthy();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should load the login component', () => {
 | 
				
			||||||
 | 
					    expect(fixture.debugElement.query(By.css('app-login'))).toBeTruthy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,81 @@
 | 
				
			|||||||
import { TestBed } from '@angular/core/testing';
 | 
					import { TestBed } from '@angular/core/testing';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { LoginService } from './login.service';
 | 
					import { LoginService } from './login.service';
 | 
				
			||||||
 | 
					import {LocalStorageService} from 'angular-2-local-storage';
 | 
				
			||||||
 | 
					import {ApiService} from './api.service';
 | 
				
			||||||
 | 
					import {Observable} from 'rxjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let loginService: LoginService;
 | 
				
			||||||
 | 
					let apiServiceSpy: jasmine.SpyObj<ApiService>;
 | 
				
			||||||
 | 
					let localStorageServiceSpy: jasmine.SpyObj<LocalStorageService>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('LoginService', () => {
 | 
					describe('LoginService', () => {
 | 
				
			||||||
  beforeEach(() => TestBed.configureTestingModule({}));
 | 
					  beforeEach(() => {
 | 
				
			||||||
 | 
					    const apiSpy = jasmine.createSpyObj('ApiService', ['get']);
 | 
				
			||||||
 | 
					    const localStorageSpy = jasmine.createSpyObj('LocalStorageService', ['set', 'remove']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TestBed.configureTestingModule({
 | 
				
			||||||
 | 
					      providers: [
 | 
				
			||||||
 | 
					        LoginService,
 | 
				
			||||||
 | 
					        {provide: ApiService, useValue: apiSpy},
 | 
				
			||||||
 | 
					        {provide: LocalStorageService, useValue: localStorageSpy}
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    loginService = TestBed.inject(LoginService);
 | 
				
			||||||
 | 
					    apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
 | 
				
			||||||
 | 
					    localStorageServiceSpy = TestBed.inject(LocalStorageService) as jasmine.SpyObj<LocalStorageService>;
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('should be created', () => {
 | 
					  it('should be created', () => {
 | 
				
			||||||
    const service: LoginService = TestBed.inject(LoginService);
 | 
					    expect(loginService).toBeTruthy();
 | 
				
			||||||
    expect(service).toBeTruthy();
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('login', () => {
 | 
				
			||||||
 | 
					    it('should store the basic auth', () => {
 | 
				
			||||||
 | 
					      localStorageServiceSpy.set.and.returnValue(true);
 | 
				
			||||||
 | 
					      apiServiceSpy.get.and.returnValue(new Observable());
 | 
				
			||||||
 | 
					      loginService.login('username', 'password');
 | 
				
			||||||
 | 
					      expect(localStorageServiceSpy.set).toHaveBeenCalledWith('basicAuth', 'dXNlcm5hbWU6cGFzc3dvcmQ=');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should remove the basic auth if login fails', () => {
 | 
				
			||||||
 | 
					      localStorageServiceSpy.set.and.returnValue(true);
 | 
				
			||||||
 | 
					      localStorageServiceSpy.remove.and.returnValue(true);
 | 
				
			||||||
 | 
					      apiServiceSpy.get.and.returnValue(new Observable(o => o.error()));
 | 
				
			||||||
 | 
					      loginService.login('username', 'password');
 | 
				
			||||||
 | 
					      expect(localStorageServiceSpy.remove.calls.count()).toBe(1);
 | 
				
			||||||
 | 
					      expect(localStorageServiceSpy.remove).toHaveBeenCalledWith('basicAuth');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should resolve true when login succeeds', async () => {
 | 
				
			||||||
 | 
					      localStorageServiceSpy.set.and.returnValue(true);
 | 
				
			||||||
 | 
					      apiServiceSpy.get.and.returnValue(new Observable(o => o.next({status: 'Authorization successful', method: 'basic'})));
 | 
				
			||||||
 | 
					      expect(await loginService.login('username', 'password')).toBeTruthy();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should resolve false when a wrong result comes in', async () => {
 | 
				
			||||||
 | 
					      localStorageServiceSpy.set.and.returnValue(true);
 | 
				
			||||||
 | 
					      apiServiceSpy.get.and.returnValue(new Observable(o => o.next({status: 'xxx', method: 'basic'})));
 | 
				
			||||||
 | 
					      expect(await loginService.login('username', 'password')).toBeFalsy();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should resolve false on an error', async () => {
 | 
				
			||||||
 | 
					      localStorageServiceSpy.set.and.returnValue(true);
 | 
				
			||||||
 | 
					      apiServiceSpy.get.and.returnValue(new Observable(o => o.error()));
 | 
				
			||||||
 | 
					      expect(await loginService.login('username', 'password')).toBeFalsy();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('canActivate', () => {
 | 
				
			||||||
 | 
					    it('should return false at first', () => {
 | 
				
			||||||
 | 
					      expect(loginService.canActivate(null, null)).toBeFalsy();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('returns true if login was successful', async () => {
 | 
				
			||||||
 | 
					      localStorageServiceSpy.set.and.returnValue(true);
 | 
				
			||||||
 | 
					      apiServiceSpy.get.and.returnValue(new Observable(o => o.next({status: 'Authorization successful', method: 'basic'})));
 | 
				
			||||||
 | 
					      await loginService.login('username', 'password');
 | 
				
			||||||
 | 
					      expect(loginService.canActivate(null, null)).toBeTruthy();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,25 +1,107 @@
 | 
				
			|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 | 
					import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
 | 
				
			||||||
 | 
					 | 
				
			||||||
import { LoginComponent } from './login.component';
 | 
					import { LoginComponent } from './login.component';
 | 
				
			||||||
 | 
					import {LoginService} from '../login.service';
 | 
				
			||||||
 | 
					import {ValidationService} from '../validation.service';
 | 
				
			||||||
 | 
					import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
 | 
				
			||||||
 | 
					import {FormsModule} from '@angular/forms';
 | 
				
			||||||
 | 
					import {By} from '@angular/platform-browser';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let validationServiceSpy: jasmine.SpyObj<ValidationService>;
 | 
				
			||||||
 | 
					let loginServiceSpy: jasmine.SpyObj<LoginService>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('LoginComponent', () => {
 | 
					describe('LoginComponent', () => {
 | 
				
			||||||
  let component: LoginComponent;
 | 
					  let component: LoginComponent;
 | 
				
			||||||
  let fixture: ComponentFixture<LoginComponent>;
 | 
					  let fixture: ComponentFixture<LoginComponent>;
 | 
				
			||||||
 | 
					  let css;   // get native element by css selector
 | 
				
			||||||
 | 
					  let cssd;  // get debug element by css selector
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  beforeEach(async(() => {
 | 
					  beforeEach(async(() => {
 | 
				
			||||||
 | 
					    const validationSpy = jasmine.createSpyObj('ValidationService', ['username', 'password']);
 | 
				
			||||||
 | 
					    const loginSpy = jasmine.createSpyObj('LoginService', ['login']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    TestBed.configureTestingModule({
 | 
					    TestBed.configureTestingModule({
 | 
				
			||||||
      declarations: [ LoginComponent ]
 | 
					      declarations: [ LoginComponent ],
 | 
				
			||||||
 | 
					      imports: [
 | 
				
			||||||
 | 
					        RbUiComponentsModule,
 | 
				
			||||||
 | 
					        FormsModule
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      providers: [
 | 
				
			||||||
 | 
					        {provide: ValidationService, useValue: validationSpy},
 | 
				
			||||||
 | 
					        {provide: LoginService, useValue: loginSpy}
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    .compileComponents();
 | 
					    .compileComponents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    validationServiceSpy = TestBed.inject(ValidationService) as jasmine.SpyObj<ValidationService>;
 | 
				
			||||||
 | 
					    loginServiceSpy = TestBed.inject(LoginService) as jasmine.SpyObj<LoginService>;
 | 
				
			||||||
  }));
 | 
					  }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  beforeEach(() => {
 | 
					  beforeEach(() => {
 | 
				
			||||||
    fixture = TestBed.createComponent(LoginComponent);
 | 
					    fixture = TestBed.createComponent(LoginComponent);
 | 
				
			||||||
    component = fixture.componentInstance;
 | 
					    component = fixture.componentInstance;
 | 
				
			||||||
    fixture.detectChanges();
 | 
					    fixture.detectChanges();
 | 
				
			||||||
 | 
					    cssd = (selector) => fixture.debugElement.query(By.css(selector));
 | 
				
			||||||
 | 
					    css = (selector) => fixture.debugElement.query(By.css(selector)).nativeElement;
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('should create', () => {
 | 
					  it('should create', () => {
 | 
				
			||||||
    expect(component).toBeTruthy();
 | 
					    expect(component).toBeTruthy();
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should have the `Please log in` heading', () => {
 | 
				
			||||||
 | 
					    expect(css('h2').innerText).toBe('Please log in');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should have empty credential inputs', () => {
 | 
				
			||||||
 | 
					    expect(css('rb-form-input[label=username] input').value).toBe('');
 | 
				
			||||||
 | 
					    expect(css('rb-form-input[label=password] input').value).toBe('');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should have an empty message at the beginning', () => {
 | 
				
			||||||
 | 
					    expect(css('.message').innerText).toBe('');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should have a login button', () => {
 | 
				
			||||||
 | 
					    expect(css('.login-button')).toBeTruthy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should display a message when a wrong username was entered', () => {
 | 
				
			||||||
 | 
					    validationServiceSpy.username.and.returnValue({ok: false, error: 'username must only contain a-z0-9-_.'});
 | 
				
			||||||
 | 
					    validationServiceSpy.password.and.returnValue({ok: true, error: ''});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cssd('.login-button').triggerEventHandler('click', null);
 | 
				
			||||||
 | 
					    fixture.detectChanges();
 | 
				
			||||||
 | 
					    expect(css('.message').innerText).toBe('username must only contain a-z0-9-_.');
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should display a message when a wrong password was entered', () => {
 | 
				
			||||||
 | 
					    validationServiceSpy.username.and.returnValue({ok: true, error: ''});
 | 
				
			||||||
 | 
					    validationServiceSpy.password.and.returnValue({ok: false, error: 'password must only contain a-zA-Z0-9!"#%&\'()*+,-./:;<=>?@[]^_`{|}~'});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cssd('.login-button').triggerEventHandler('click', null);
 | 
				
			||||||
 | 
					    fixture.detectChanges();
 | 
				
			||||||
 | 
					    expect(css('.message').innerText).toBe('password must only contain a-zA-Z0-9!"#%&\'()*+,-./:;<=>?@[]^_`{|}~');
 | 
				
			||||||
 | 
					    expect(loginServiceSpy.login).not.toHaveBeenCalled();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should call the LoginService with valid credentials', () => {
 | 
				
			||||||
 | 
					    validationServiceSpy.username.and.returnValue({ok: true, error: ''});
 | 
				
			||||||
 | 
					    validationServiceSpy.password.and.returnValue({ok: true, error: ''});
 | 
				
			||||||
 | 
					    loginServiceSpy.login.and.returnValue(new Promise(r => r(true)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cssd('.login-button').triggerEventHandler('click', null);
 | 
				
			||||||
 | 
					    expect(loginServiceSpy.login.calls.count()).toBe(1);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should display an error if the LoginService could not authenticate', fakeAsync(() => {
 | 
				
			||||||
 | 
					    validationServiceSpy.username.and.returnValue({ok: true, error: ''});
 | 
				
			||||||
 | 
					    validationServiceSpy.password.and.returnValue({ok: true, error: ''});
 | 
				
			||||||
 | 
					    loginServiceSpy.login.and.returnValue(new Promise(r => r(false)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cssd('.login-button').triggerEventHandler('click', null);
 | 
				
			||||||
 | 
					    expect(loginServiceSpy.login.calls.count()).toBe(1);
 | 
				
			||||||
 | 
					    tick();
 | 
				
			||||||
 | 
					    fixture.detectChanges();
 | 
				
			||||||
 | 
					    expect(css('.message').innerText).toBe('Wrong credentials! Try again.');
 | 
				
			||||||
 | 
					  }));
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,12 +25,11 @@ export class LoginComponent implements OnInit {
 | 
				
			|||||||
  login() {
 | 
					  login() {
 | 
				
			||||||
    const {ok: userOk, error: userError} = this.validate.username(this.username);
 | 
					    const {ok: userOk, error: userError} = this.validate.username(this.username);
 | 
				
			||||||
    const {ok: passwordOk, error: passwordError} = this.validate.password(this.password);
 | 
					    const {ok: passwordOk, error: passwordError} = this.validate.password(this.password);
 | 
				
			||||||
    this.message = userError + (userError + passwordError === '' ? '' : '\n') + passwordError;  // display errors
 | 
					    this.message = userError + (userError !== '' && passwordError !== '' ? '\n' : '') + passwordError;  // display errors
 | 
				
			||||||
    console.log(this.message);
 | 
					 | 
				
			||||||
    if (userOk && passwordOk) {
 | 
					    if (userOk && passwordOk) {
 | 
				
			||||||
      this.loginService.login(this.username, this.password).then(ok => {
 | 
					      this.loginService.login(this.username, this.password).then(ok => {
 | 
				
			||||||
        if (ok) {
 | 
					        if (ok) {
 | 
				
			||||||
          this.message = 'Login successful';  // TODO: think about following action, write tests!
 | 
					          this.message = 'Login successful';  // TODO: think about following action
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
          this.message = 'Wrong credentials! Try again.';
 | 
					          this.message = 'Wrong credentials! Try again.';
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								src/app/samples/samples.component.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/app/samples/samples.component.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<p>samples works!</p>
 | 
				
			||||||
							
								
								
									
										0
									
								
								src/app/samples/samples.component.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/app/samples/samples.component.scss
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										25
									
								
								src/app/samples/samples.component.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/app/samples/samples.component.spec.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { SamplesComponent } from './samples.component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('SamplesComponent', () => {
 | 
				
			||||||
 | 
					  let component: SamplesComponent;
 | 
				
			||||||
 | 
					  let fixture: ComponentFixture<SamplesComponent>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(async(() => {
 | 
				
			||||||
 | 
					    TestBed.configureTestingModule({
 | 
				
			||||||
 | 
					      declarations: [ SamplesComponent ]
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .compileComponents();
 | 
				
			||||||
 | 
					  }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(() => {
 | 
				
			||||||
 | 
					    fixture = TestBed.createComponent(SamplesComponent);
 | 
				
			||||||
 | 
					    component = fixture.componentInstance;
 | 
				
			||||||
 | 
					    fixture.detectChanges();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should create', () => {
 | 
				
			||||||
 | 
					    expect(component).toBeTruthy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/app/samples/samples.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/app/samples/samples.component.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					import { Component, OnInit } from '@angular/core';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
					  selector: 'app-samples',
 | 
				
			||||||
 | 
					  templateUrl: './samples.component.html',
 | 
				
			||||||
 | 
					  styleUrls: ['./samples.component.scss']
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class SamplesComponent implements OnInit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ngOnInit(): void {
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,12 +1,35 @@
 | 
				
			|||||||
import { TestBed } from '@angular/core/testing';
 | 
					import { TestBed } from '@angular/core/testing';
 | 
				
			||||||
 | 
					 | 
				
			||||||
import { ValidationService } from './validation.service';
 | 
					import { ValidationService } from './validation.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let validationService: ValidationService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('ValidationService', () => {
 | 
					describe('ValidationService', () => {
 | 
				
			||||||
  beforeEach(() => TestBed.configureTestingModule({}));
 | 
					  beforeEach(() => {
 | 
				
			||||||
 | 
					    TestBed.configureTestingModule({
 | 
				
			||||||
 | 
					      providers: [ValidationService]
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    validationService = TestBed.inject(ValidationService);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('should be created', () => {
 | 
					  it('should be created', () => {
 | 
				
			||||||
    const service: ValidationService = TestBed.inject(ValidationService);
 | 
					    expect(validationService).toBeTruthy();
 | 
				
			||||||
    expect(service).toBeTruthy();
 | 
					 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should return true on a correct username', () => {
 | 
				
			||||||
 | 
					    expect(validationService.username('abc')).toEqual({ok: true, error: ''});
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should return an error on an incorrect username', () => {
 | 
				
			||||||
 | 
					    expect(validationService.username('abc#')).toEqual({ok: false, error: 'username must only contain a-z0-9-_.'});
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should return true on a correct password', () => {
 | 
				
			||||||
 | 
					    expect(validationService.password('Abc123!#')).toEqual({ok: true, error: ''});
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should return an error on an incorrect password', () => {
 | 
				
			||||||
 | 
					    expect(validationService.password('Abc123')).toEqual({ok: false, error: 'password must only contain a-zA-Z0-9!"#%&\'()*+,-./:;<=>?@[]^_`{|}~'});
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "/": {
 | 
					  "/api": {
 | 
				
			||||||
    "target": "http://localhost:3000",
 | 
					    "target": "http://localhost:3000",
 | 
				
			||||||
    "secure": false
 | 
					    "secure": false
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@
 | 
				
			|||||||
    "src/polyfills.ts"
 | 
					    "src/polyfills.ts"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "include": [
 | 
					  "include": [
 | 
				
			||||||
    "src/**/*.ts"
 | 
					    "src/**/*.d.ts"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "exclude": [
 | 
					  "exclude": [
 | 
				
			||||||
    "src/test.ts",
 | 
					    "src/test.ts",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user