Optimize Component tests; Fix e2e execution

unit-test
Florian Hartwich 2017-04-15 23:23:21 +02:00
parent 704f426eea
commit 38a53b4001
9 changed files with 76 additions and 59 deletions

View File

@ -13,6 +13,7 @@ export class TaskEditPage extends AbstractHeaderPage {
assigneeName = element(by.id('assignee_name')); assigneeName = element(by.id('assignee_name'));
assigneeEmail = element(by.id('assignee_email')); assigneeEmail = element(by.id('assignee_email'));
saveButton = element(by.id('save')); saveButton = element(by.id('save'));
cancelButton = element(by.id('cancel'));
constructor(newTask: boolean) { constructor(newTask: boolean) {
super(); super();
@ -56,7 +57,12 @@ export class TaskEditPage extends AbstractHeaderPage {
return new TaskOverviewPage; return new TaskOverviewPage;
} }
validateInput(elementId: string, value: string) { cancelSubmitTask() : TaskOverviewPage {
this.cancelButton.click();
return new TaskOverviewPage();
}
static validateInput(elementId: string, value: string) {
const input = element(by.id(elementId)); const input = element(by.id(elementId));
expect(input.getAttribute('value')).toBe(value); expect(input.getAttribute('value')).toBe(value);
} }

View File

@ -16,6 +16,8 @@ describe('Edit Task Form', function () {
} }
}; };
const newTitle = 'Ersten Prototyp mit Angular 4.0 entwickelt';
it('should load task with its values in edit form', () => { it('should load task with its values in edit form', () => {
browser.get('/tasks'); browser.get('/tasks');
const taskOverviewPage = new TaskOverviewPage; const taskOverviewPage = new TaskOverviewPage;
@ -23,16 +25,15 @@ describe('Edit Task Form', function () {
const taskEditPage = taskOverviewPage.clickTask(dbTask.title); const taskEditPage = taskOverviewPage.clickTask(dbTask.title);
// check for correct url - test input field values // check for correct url - test input field values
taskEditPage.validateCurrentUrl('tasks/edit/' + dbTask.id); taskEditPage.validateCurrentUrl('tasks/edit/' + dbTask.id);
taskEditPage.validateInput('title', dbTask.title); TaskEditPage.validateInput('title', dbTask.title);
taskEditPage.validateInput('description', dbTask.description); TaskEditPage.validateInput('description', dbTask.description);
taskEditPage.validateInput('state', dbTask.state); TaskEditPage.validateInput('state', dbTask.state);
taskEditPage.validateInput('assignee_name', dbTask.assignee['name']) TaskEditPage.validateInput('assignee_name', dbTask.assignee['name'])
taskEditPage.validateInput('assignee_email', dbTask.assignee['email']) TaskEditPage.validateInput('assignee_email', dbTask.assignee['email'])
}); });
it('should have updated title in overview after edit, but same task id as before', () => { it('should have updated title in overview after edit, but same task id as before', () => {
browser.get('/tasks/edit/' + dbTask.id); browser.get('/tasks/edit/' + dbTask.id);
const newTitle = 'Ersten Prototyp mit Angular 4.0 entwickelt';
const taskEditPage = new TaskEditPage(false); const taskEditPage = new TaskEditPage(false);
taskEditPage.clearEnterTitle(newTitle); taskEditPage.clearEnterTitle(newTitle);
let taskOverviewPage = taskEditPage.submitTaskForm(); let taskOverviewPage = taskEditPage.submitTaskForm();
@ -41,5 +42,12 @@ describe('Edit Task Form', function () {
taskOverviewPage.clickTask(newTitle).validateCurrentUrl('tasks/edit/' + dbTask.id); taskOverviewPage.clickTask(newTitle).validateCurrentUrl('tasks/edit/' + dbTask.id);
}); });
it('should have return to Overview after cancel button click', () => {
browser.get('/tasks/edit/' + dbTask.id);
const taskEditPage = new TaskEditPage(false);
const taskOverviewPage = taskEditPage.cancelSubmitTask();
taskOverviewPage.verifyNewTask(newTitle);
});
}); });

View File

@ -6,11 +6,11 @@
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"start": "concurrently \"node projects-server/server.js db=projects-server/db.json\" \"ng serve\" ", "start": "concurrently \"node projects-server/server.js db=projects-server/db.json\" \"ng serve\" ",
"starte2e": "concurrently \"node projects-server/server.js db=projects-server/test.json\" \"ng serve --env=e2e\" ", "starte2e": "cp ./projects-server/safe/test.json ./projects-server/test.json && concurrently \"node projects-server/server.js db=projects-server/test.json\" \"ng serve --env=e2e\" ",
"lint": "tslint \"src/**/*.ts\" --project src/tsconfig.json --type-check && tslint \"e2e/**/*.ts\" --project e2e/tsconfig.json --type-check", "lint": "tslint \"src/**/*.ts\" --project src/tsconfig.json --type-check && tslint \"e2e/**/*.ts\" --project e2e/tsconfig.json --type-check",
"test": "ng test", "test": "ng test",
"pree2e": "cp ./projects-server/safe/test.json ./projects-server/test.json && webdriver-manager update --standalone false --gecko false", "pree2e": "webdriver-manager update --standalone false --gecko false",
"e2e": "concurrently \"node projects-server/server.js db=projects-server/test.json\" \"ng e2e --env=e2e\" ", "e2e": "cp ./projects-server/safe/test.json ./projects-server/test.json && concurrently \"node projects-server/server.js db=projects-server/test.json\" \"ng e2e --env=e2e\" ",
"install-server": "npm install --prefix ./projects-server ./projects-server", "install-server": "npm install --prefix ./projects-server ./projects-server",
"e2e-screenshots": "protractor ./protractor-html-reporter.conf.js", "e2e-screenshots": "protractor ./protractor-html-reporter.conf.js",
"postinstall": "npm run install-server" "postinstall": "npm run install-server"

View File

@ -3,7 +3,7 @@ import {BlogEntryComponent} from "./blog-entry.component";
import {BlogEntry} from "./blog-entry"; import {BlogEntry} from "./blog-entry";
import {BlogComponent} from "../blog.component"; import {BlogComponent} from "../blog.component";
import {RouterTestingModule} from "@angular/router/testing"; import {RouterTestingModule} from "@angular/router/testing";
import {Component} from "@angular/core"; import {MockBlogComponent} from "../../mocks/mock-blog.component";
describe('Blog Entry Isolated Test', () => { describe('Blog Entry Isolated Test', () => {
@ -52,38 +52,12 @@ describe('Blog Entry Isolated Test', () => {
const blogDelete = element.querySelector('div /deep/ .blog-delete > button').textContent; const blogDelete = element.querySelector('div /deep/ .blog-delete > button').textContent;
expect(blogDelete).toBe("Entfernen") expect(blogDelete).toBe("Entfernen")
// keine Überprüfung der id, die lediglich im EventListener des Delete Button hinterlegt ist, möglich!
// nur durch click-Event auslösen, was jedoch BlogComponent vorraussetzt
}); });
}); });
describe('BlogEntryComp -> BlogComp Dependent Test', () => { describe('BlogEntryComp -> BlogComp Dependent Test', () => {
it('should remove entry from BlogComponent on "delete" button click', () => {
TestBed.configureTestingModule({
declarations: [BlogEntryComponent, MockBlogComponent]
});
const entryFixture = TestBed.createComponent(BlogEntryComponent);
const entryInstance: BlogEntryComponent = entryFixture.componentInstance;
const blogFixture = TestBed.createComponent(MockBlogComponent);
const blogInstance: any = blogFixture.componentInstance;
const blogEntry: BlogEntry = blogInstance.entries[0];
entryInstance.entry = blogEntry;
entryInstance.blogComponent = blogInstance;
const oldLength = blogInstance.entries.length;
entryFixture.nativeElement.querySelector('div /deep/ .blog-delete > button').click();
expect(blogInstance.entries.length).toBe(oldLength - 1);
});
it('should remove entry from BlogComponent on "delete" button click : OVERRIDE BLOG TEMPLATE', () => { it('should remove entry from BlogComponent on "delete" button click : OVERRIDE BLOG TEMPLATE', () => {
TestBed.overrideComponent(BlogComponent, { TestBed.overrideComponent(BlogComponent, {
@ -103,34 +77,45 @@ describe('Blog Entry Isolated Test', () => {
const blogFixture = TestBed.createComponent(BlogComponent); const blogFixture = TestBed.createComponent(BlogComponent);
const blogInstance: BlogComponent = blogFixture.componentInstance; const blogInstance: BlogComponent = blogFixture.componentInstance;
const blogEntry: BlogEntry = blogInstance.entries[0]; entryInstance.entry = blogInstance.entries[0];
entryInstance.entry = blogEntry;
entryInstance.blogComponent = blogInstance; entryInstance.blogComponent = blogInstance;
const oldLength = blogInstance.entries.length; const oldLength = blogInstance.entries.length;
entryFixture.nativeElement.querySelector('div /deep/ .blog-delete > button').click(); entryFixture.nativeElement.querySelector('div /deep/ .blog-delete > button').click();
expect(blogInstance.entries.length).toBe(oldLength - 1); expect(blogInstance.entries.length).toBe(oldLength - 1);
});
}); for (let entry in blogInstance.entries) {
expect(entry).not.toBe(entryInstance.entry);
});
// Mocked Blog Component
@Component({
selector: 'blog',
template: '<blog-entry></blog-entry>'
})
export class MockBlogComponent {
entries = [{}, {}];
deleteBlogEntry(id) {
this.entries.splice(0, 1);
} }
});
it('should remove entry from BlogComponent on "delete" button click : MOCK BLOG COMPONENT', () => {
TestBed.configureTestingModule({
declarations: [BlogEntryComponent, MockBlogComponent]
});
const entryFixture = TestBed.createComponent(BlogEntryComponent);
const entryInstance: BlogEntryComponent = entryFixture.componentInstance;
const blogFixture = TestBed.createComponent(MockBlogComponent);
const blogInstance: any = blogFixture.componentInstance;
entryInstance.entry = blogInstance.entries[0];
entryInstance.blogComponent = blogInstance;
const oldLength = blogInstance.entries.length;
entryFixture.nativeElement.querySelector('div /deep/ .blog-delete > button').click();
expect(blogInstance.entries.length).toBe(oldLength - 1);
for (let entry in blogInstance.entries) {
expect(entry).not.toBe(entryInstance.entry);
} }
});
});
});

View File

@ -53,6 +53,10 @@ export class BlogComponent {
this.entries.push(entry); this.entries.push(entry);
} }
/**
* Löscht den Eintrag mit der gegebenen ID aus der Liste
* @param id - Objekt-ID des zu löschenden Eintrags
*/
deleteBlogEntry(id: number) { deleteBlogEntry(id: number) {
let entryIndex = this.entries.findIndex(entry => entry.id === id); let entryIndex = this.entries.findIndex(entry => entry.id === id);
if (entryIndex >= 0) { if (entryIndex >= 0) {

View File

@ -3,7 +3,7 @@ import {LoginComponent} from "./login.component";
import {RouterTestingModule} from "@angular/router/testing"; import {RouterTestingModule} from "@angular/router/testing";
import {LoginService} from "../services/login-service/login-service"; import {LoginService} from "../services/login-service/login-service";
import {FormsModule} from "@angular/forms"; import {FormsModule} from "@angular/forms";
import {MockLoginService} from "../mocks/mock-login-service.spec"; import {MockEmptyClass} from "../mocks/mock-empty-class";
import Spy = jasmine.Spy; import Spy = jasmine.Spy;
@ -14,14 +14,13 @@ describe('Login Component Template Driven Form Test with Spy', () => {
imports: [FormsModule, RouterTestingModule.withRoutes([])], imports: [FormsModule, RouterTestingModule.withRoutes([])],
declarations: [LoginComponent], declarations: [LoginComponent],
providers: [ providers: [
{provide: LoginService, useClass: MockLoginService} {provide: LoginService, useClass: MockEmptyClass}
], ],
}) })
}); });
it('should be possible to request login', () => { it('should be possible to request login', () => {
const inputUser = 'testuser'; const inputUser = 'testuser';
const inputPass = 'testpass'; const inputPass = 'testpass';

View File

@ -0,0 +1,15 @@
import {Component} from "@angular/core";
@Component({
selector: 'blog',
template: '<blog-entry *ngFor="let entry of entries" [entry]="entry" [blogComponent]="this"></blog-entry>'
})
export class MockBlogComponent {
entries = [{id: 1}, {id: 2}];
deleteBlogEntry(id) {
this.entries.splice(0, 1);
}
}

View File

@ -0,0 +1,3 @@
export class MockEmptyClass {
}

View File

@ -1,3 +0,0 @@
export class MockLoginService {
}