Final - Doc for new classes

unit-test
Florian Hartwich 2017-04-18 00:50:52 +02:00
parent 68faa52098
commit 345d8f4a5e
15 changed files with 201 additions and 54 deletions

View File

@ -2,6 +2,12 @@ import {browser, element, by} from 'protractor';
import {AbstractHeaderPage} from "../page-object/abstract-header.po";
import {TaskOverviewPage} from "../page-object/task/task-overview.po";
/**
* E2E-Test für grundsätzlichen Seitenzugriff und die Seitennavigation
* bezüglich AbstractPageHeader Implementierung
*
* @author FHartwich
*/
describe('Access Projectmanager Homepage', function () {
beforeEach(() => {

View File

@ -2,19 +2,57 @@ import {AbstractHeaderPage} from "../abstract-header.po";
import {by, element} from "protractor";
import {TaskOverviewPage} from "./task-overview.po";
/**
* PageObject Klasse, repräsentiert die Formularseite zum
* editieren und Erstellen von Aufgaben
*
* @author FHartwich
*/
export class TaskEditPage extends AbstractHeaderPage {
/**
* Array mit möglichen Fehleranzeigen
* @type {{title: string; email: string}}
*/
errorMessages = {title: 'Titel muss mindestens 5 Zeichen enthalten',
email : 'Bitte geben Sie eine gültige E-Mail Adresse an'};
/**
* Eingabefeld - Titel
* @type {ElementFinder}
*/
titleInput = element(by.id('title'));
/**
* Eingabefeld - Beschreibung
* @type {ElementFinder}
*/
descriptionInput = element(by.id('description'));
statusDropdown = element(by.id('state'));
assigneeName = element(by.id('assignee_name'));
/**
* Eingabefeld - Verantwortlicher, eMail
* @type {ElementFinder}
*/
assigneeEmail = element(by.id('assignee_email'));
/**
* Speichern - Button
* @type {ElementFinder}
*/
saveButton = element(by.id('save'));
/**
* Abbrechen - Button
* @type {ElementFinder}
*/
cancelButton = element(by.id('cancel'));
/**
* Konstruktor
* @param newTask - true, wenn die Seite für einen neuen Tasks geöffnet wird
* false, wenn ein Task editiert wird
*/
constructor(newTask: boolean) {
super();
let headline;
@ -26,47 +64,65 @@ export class TaskEditPage extends AbstractHeaderPage {
super.validatePageHeadline(headline)
}
/**
* Löscht alten Titel und gibt neuen ein
* @param title - neuer Titel
*/
clearEnterTitle(title: string) {
this.titleInput.clear();
this.titleInput.sendKeys(title);
}
/**
* Löscht alte Beschreibung und gibt neue ein
* @param description - neue Beschreibung
*/
clearEnterDescription(description: string) {
this.descriptionInput.clear();
this.descriptionInput.sendKeys(description);
}
setStatus(state: string) {
this.statusDropdown.element(by.css('[value="${state}"]'))
.click()// -> Höller, Christoph - Angular, S. 562 - Listing 14.12
}
clearInsertName(name: string) {
this.assigneeName.clear();
this.assigneeName.sendKeys(name);
}
/**
* Löscht alte Assignee eMail und trägt neue ein
* @param email - neue eMail Adresse
*/
clearInsertEmail(email: string) {
this.assigneeEmail.clear();
this.assigneeEmail.sendKeys(email);
}
/**
* Klick auf den Button zum absenden des Formulars
* @returns {TaskOverviewPage}
*/
submitTaskForm() {
this.saveButton.click();
return new TaskOverviewPage;
}
/**
* Klick auf den Button zum Abbrechen der Formulareingabe
* @returns {TaskOverviewPage}
*/
cancelSubmitTask() : TaskOverviewPage {
this.cancelButton.click();
return new TaskOverviewPage();
}
/**
* überprüft den Feldwert des über die ID beschriebenen Elements
* @param elementId - CSS ID des Testfeldes
* @param value - erwarteter Wert
*/
static validateInput(elementId: string, value: string) {
const input = element(by.id(elementId));
expect(input.getAttribute('value')).toBe(value);
}
/**
* prüft ob ein Error existiert der diesen Wert hat
* @param input - erwartete Fehlermeldung
*/
validateError(input: string) {
expect(element(by.className('alert')).getText())
.toBe(this.errorMessages[input]);

View File

@ -2,11 +2,26 @@ import {AbstractHeaderPage} from "../abstract-header.po";
import {browser, by, element, ElementArrayFinder, ElementFinder, ExpectedConditions} from "protractor";
import {TaskEditPage} from "./task-edit.po";
/**
* PageObject Klasse als Repräösentation der Aufgabenübersichts-Seite
*
* @author FHartwich
*/
export class TaskOverviewPage extends AbstractHeaderPage {
/**
* Button zum Anlegen einer neuen Aufgabe
*/
neueAufgabeBtn: ElementFinder;
/**
* Liste aller Einträge
*/
taskEntries: ElementArrayFinder;
/**
* Konstruktor
*/
constructor() {
super();
super.validatePageHeadline('Aufgaben durchsuchen');
@ -14,21 +29,39 @@ export class TaskOverviewPage extends AbstractHeaderPage {
this.taskEntries = element.all(by.className('task-list-entry'));
}
/**
* Prüft den Wert im Suchfeld
* @param value - erwarteter Wert
*/
validateSearchFieldValue(value: string) {
const inputField = element(by.id('search-tasks'));
expect(inputField.getAttribute('value')).toEqual(value);
}
/**
* Klick auf den Button zum Erstellen einer neuen Aufgabe
* @returns {TaskEditPage}
*/
clickNeueAufgabe(): TaskEditPage {
this.neueAufgabeBtn.click();
return new TaskEditPage(true);
}
/**
* validiert dass ein Task mit gegebenen Titel in der Liste
* vorhanden ist
* @param title - erwarteter Titel
*/
verifyNewTask(title: string) {
const newEntry = element(by.linkText(title));
browser.wait(ExpectedConditions.presenceOf(newEntry));
}
/**
* Klick auf den Link einer Aufgabe mit gegebenen Titel
* @param title - Titel der Aufgabe
* @returns {TaskEditPage}
*/
clickTask(title: string) {
const entry = element(by.linkText(title));
entry.click();

View File

@ -3,7 +3,7 @@ import {TaskOverviewPage} from "../page-object/task/task-overview.po";
import {TaskEditPage} from "../page-object/task/task-edit.po";
/**
* E2E Testsuite für seitenübergreifende
* E2E Test für seitenübergreifende
* Interaktionen beim Erstellen einer neuen Aufagbe
*
* @author FHartwich

View File

@ -2,7 +2,7 @@
"tasks": [
{
"id": 3,
"title": "Ersten Prototyp mit Angular 4.0 entwickelt",
"title": "Ersten Prototyp mit Angular 2.0 entwickeln",
"description": "Der Prototyp soll zeigen, wie Routing und HTTP-Anbindung umgesetzt werden können.",
"tags": [],
"state": "IN_PROGRESS",
@ -57,15 +57,6 @@
"state": "IN_PROGRESS",
"title": "New Task",
"id": 9
},
{
"assignee": {
"email": "testuser@test.com"
},
"tags": [],
"state": "BACKLOG",
"title": "valid title",
"id": 10
}
]
}

View File

@ -5,6 +5,12 @@ import {BlogComponent} from "../blog.component";
import {RouterTestingModule} from "@angular/router/testing";
import {MockBlogComponent} from "../../mocks/mock-blog.component";
/**
* Test für die Klasse BlogEntryComponent
* isoliert und in Abhängigkeit zu BlogComponent
*
* @author FHartwich
*/
describe('Blog Entry Isolated Test', () => {
describe('Isolated Test', () => {

View File

@ -1,11 +1,17 @@
import {BlogComponent} from './blog.component'
import {async, inject, TestBed} from "@angular/core/testing";
import {BlogComponent} from "./blog.component";
import {async, TestBed} from "@angular/core/testing";
import {RouterTestingModule} from "@angular/router/testing";
import {Component, CUSTOM_ELEMENTS_SCHEMA} from "@angular/core";
import {CUSTOM_ELEMENTS_SCHEMA} from "@angular/core";
import {By} from "@angular/platform-browser";
import {BlogEntryComponent} from "./blog-entry/blog-entry.component";;
import {Router} from "@angular/router/router";
import {BlogEntryComponent} from "./blog-entry/blog-entry.component";
;
/**
* Test für die BlogComponent Klasse, z.T.mit
* sich wiederholenden Tesfällen, verschiedenen Kontextumfangs
*
* @author FHartwich
*/
describe('Blog Component', () => {
describe('Isolated Component Test', () => {
@ -15,10 +21,10 @@ describe('Blog Component', () => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([])],
declarations: [BlogComponent]
});
});
});
beforeEach(async(()=> {
beforeEach(async(() => {
TestBed.overrideComponent(BlogComponent, {set: {template: ''}});
blogComponent = TestBed.createComponent(BlogComponent).componentInstance;
}));

View File

@ -6,7 +6,12 @@ import {FormsModule} from "@angular/forms";
import {MockLoginService} from "../mocks/mock-login-service";
import Spy = jasmine.Spy;
/**
* Test für die LoginComponent Klasse
* für Formulareingabe und Service Interaktion
*
* @author FHartwich
*/
describe('Login Component UI Driven Form Test with Spy', () => {
beforeEach(() => {

View File

@ -1,5 +1,12 @@
import {Component} from "@angular/core";
/**
* Gemockte Klasse basierend auf BlogComponent,
* die lediglich die Directive und zwei minimal-Einträge
* des BlogEntry zur Interaktion bereitstellt
*
* @author FHartwich
*/
@Component({
selector: 'blog',
template: '<blog-entry *ngFor="let entry of entries" [entry]="entry" [blogComponent]="this"></blog-entry>'

View File

@ -1,5 +1,12 @@
/**
* Klasse mit einzelner, leerer Methode
* als Mock zum Testen der Service-Interaktion
*
* @author FHartwich
*/
export class MockLoginService {
login(name, password) {};
login(name, password) {
};
}

View File

@ -1,5 +1,11 @@
import {Component} from "@angular/core";
/**
* Mock für die TaskItemComponent
* zur Nutzung als leere Klasse ohne Interaktion
*
* @author FHartwich
*/
@Component({
selector: 'pjm-task-item',
template: '',

View File

@ -1,11 +1,18 @@
import {FormGroup, ReactiveFormsModule} from '@angular/forms';
import {TestBed} from '@angular/core/testing';
import {ModelDrivenFormComponent} from './model-driven-form.component';
import {UserService} from '../services/user-service/user.service';
import {FormGroup, ReactiveFormsModule} from "@angular/forms";
import {TestBed} from "@angular/core/testing";
import {ModelDrivenFormComponent} from "./model-driven-form.component";
import {UserService} from "../services/user-service/user.service";
import {TaskServiceModelForm} from "../services/task-service/task-model-form.service";
import {ShowErrorComponentModelDriven} from "../show-error/show-error-model-driven.component";
import {generateRandomString} from "../test/test.helper";
/**
* Test für die ModelDrivenFormComponent mit Interaktion
* auf Grundlage des Modell-Getriebenen-Formulars (FormGroup)
*
* @author FHartwich
*/
describe('Model Driven Form', () => {
// ModelDrivenFormComponent Fixture

View File

@ -7,8 +7,11 @@ import {LoginService} from "./login-service";
import {UserStore} from "../stores/user.store";
/**
* Test für die LoginService Klasse
* Initialisierung und Durchführung nach Vorlage aus dem
* TaskService Tests (../task-service/task.service.spec.ts) von Christoph Höller
*
* @author FHartwich
*/
describe('Login-Service', () => {
beforeEach(() => {
@ -47,7 +50,7 @@ describe('Login-Service', () => {
const expectedUrl = 'http://localhost:3000/api/users?name=admin';
expect(connection.request.url).toBe(expectedUrl);
expect(connection.request.method).toBe(RequestMethod.Get);
const response = new ResponseOptions({body: JSON.stringify(user)});
const response = new ResponseOptions({body: JSON.stringify(user)});
connection.mockRespond(new Response(response));
});
loginService.getUser('admin');

View File

@ -1,14 +1,22 @@
import {TaskService} from '../../services/task-service/task.service';
import {RouterTestingModule} from '@angular/router/testing';
import {TestBed} from '@angular/core/testing';
import {EditTaskComponent} from './edit-task.component';
import {ShowErrorComponent} from '../../show-error/show-error.component';
import {APPLICATION_VALIDATORS} from '../../models/app-validators';
import {Title} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
import {MockTaskService} from '../../mocks/mock-task-service';
import {TaskService} from "../../services/task-service/task.service";
import {RouterTestingModule} from "@angular/router/testing";
import {TestBed} from "@angular/core/testing";
import {EditTaskComponent} from "./edit-task.component";
import {ShowErrorComponent} from "../../show-error/show-error.component";
import {APPLICATION_VALIDATORS} from "../../models/app-validators";
import {Title} from "@angular/platform-browser";
import {FormsModule} from "@angular/forms";
import {MockTaskService} from "../../mocks/mock-task-service";
import {generateRandomString} from "../../test/test.helper";
/**
* Test für die Klasse EditTaskComponent
* zur Prüfung von Formularinteraktion auf Grundlage
* eines Template-Getriebenen-Formulars
*
* @author FHartwich
*/
describe('EditTask Component', () => {
describe('Template Driven Form API-based Test', () => {

View File

@ -1,14 +1,20 @@
import {async, TestBed} from "@angular/core/testing";
import {async, inject, TestBed} from "@angular/core/testing";
import {Router} from "@angular/router";
import {ReactiveFormsModule} from "@angular/forms";
import {inject} from "@angular/core/testing";
import {TaskListComponent} from "./task-list.component";
import {RouterTestingModule} from "@angular/router/testing";
import {MockTaskService} from "../../mocks/mock-task-service";
import {TaskService} from "../../services/task-service/task.service";
import {MockTaskItemComponent} from '../../mocks/mock-task-item.component'
import {MockTaskItemComponent} from "../../mocks/mock-task-item.component";
describe('Task Overview Component Routing', () => {
/**
* Test der TaskListComponent
* im Hinblick auf die Router-Iteraktion
*
* @author FHartwich
*/
describe('Task List Component Routing', () => {
let component: TaskListComponent;
let fixture;
@ -17,7 +23,7 @@ describe('Task Overview Component Routing', () => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule, RouterTestingModule.withRoutes([])],
declarations: [TaskListComponent, MockTaskItemComponent],
providers: [ {provide: TaskService, useClass: MockTaskService} ]
providers: [{provide: TaskService, useClass: MockTaskService}]
});
fixture = TestBed.createComponent(TaskListComponent);
component = fixture.componentInstance;
@ -29,7 +35,7 @@ describe('Task Overview Component Routing', () => {
})
);
it('should call Router.navigate with id to open quickedit ',() => {
it('should call Router.navigate with id to open quickedit ', () => {
fixture.whenStable().then(() => {
let taskId = 12;
let spyNavigation = spyOn(router, 'navigate');
@ -37,7 +43,7 @@ describe('Task Overview Component Routing', () => {
component.selectTask(taskId);
expect(spyNavigation).toHaveBeenCalled();
expect(spyNavigation.calls.first().args[0])
.toContain({outlets: {'right': ['overview', taskId]}});
.toContain({outlets: {'right': ['overview', taskId]}});
});
});