diff --git a/README.md b/README.md
index c219308..235dff4 100644
--- a/README.md
+++ b/README.md
@@ -49,6 +49,11 @@ All the scenarios are listed here below and nicely linked to the source file.
* [custom filter pipe](./src/app/pipes/filter.pipe.spec.ts)
* [async pipes within templates](./src/app/components/async-stream.component.spec.ts)
_Shows how to correctly resolve async pipes and then verify they properly render in the HTML_
+1. [**Testing Custom Directives**](./src/app/directives)
+ * [custom email Validator directive](./src/app/directives/emailvalidator.spec.ts)
+ _Testing Custom Email Validator directive for template driven form_
+ * [update on hover directive](./src/app/directives/updateonhover.directive.spec.ts)
+ _Testing simple custom directive which makes use of HostListener and HostBinding_
1. [**Custom Matchers and Utilities**](./src/app/utils)
* [Create your own custom Jasmine matchers](./src/app/utils/custom-matchers.ts)
diff --git a/src/app/directives/emailvalidator.directive.ts b/src/app/directives/emailvalidator.directive.ts
new file mode 100644
index 0000000..2948cfd
--- /dev/null
+++ b/src/app/directives/emailvalidator.directive.ts
@@ -0,0 +1,30 @@
+import { Directive } from '@angular/core';
+import { NG_VALIDATORS, FormControl } from '@angular/forms';
+
+@Directive({
+ selector: '[validateEmail][ngModel],[validateEmail][formControl]',
+ providers: [
+ { provide: NG_VALIDATORS, useClass: EmailValidator, multi: true }
+ ]
+})
+export class EmailValidator {
+
+ constructor() { }
+
+ validate(formControl: FormControl) {
+ let EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
+
+ let temporaryDomains = ['yopmail.com', 'getnada.com', 'boximail.com', 'robot-mail.com', 'zetmail.com', 'givemail.com']
+
+ const cValue = formControl.value;
+ if(EMAIL_REGEXP.test(formControl.value) && temporaryDomains.indexOf(cValue.split('@')[1]) === -1 ) {
+ return null;
+ } else {
+ return {
+ validateEmail: {
+ valid: false
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/directives/emailvalidator.spec.ts b/src/app/directives/emailvalidator.spec.ts
new file mode 100644
index 0000000..ebb9f6e
--- /dev/null
+++ b/src/app/directives/emailvalidator.spec.ts
@@ -0,0 +1,78 @@
+import { TestBed, ComponentFixture } from '@angular/core/testing';
+import { FormsModule } from "@angular/forms";
+import { ViewChild, Component } from '@angular/core';
+import { EmailValidator } from './emailvalidator.directive';
+
+@Component({
+ template: `
+
+ `
+})
+class TestTemplateDrivenFormsComponent {
+ @ViewChild('f') form: any;
+ model = {
+ email: '',
+ password: ''
+ };
+ constructor() { }
+ ngOnInit() { }
+}
+
+describe('Directive: EmailValidator using TestTemplateDrivenFormsComponent', () => {
+
+ let component: TestTemplateDrivenFormsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(() => {
+
+ TestBed.configureTestingModule({
+ imports: [FormsModule],
+ declarations: [TestTemplateDrivenFormsComponent, EmailValidator]
+ });
+
+ fixture = TestBed.createComponent(TestTemplateDrivenFormsComponent);
+
+ component = fixture.componentInstance;
+
+ fixture.detectChanges();
+
+ });
+
+ it('Email invalid when not filled', () => {
+ fixture.whenStable().then( () => {
+ fixture.detectChanges();
+ expect(component.form.valid).toBeFalsy();
+ expect(component.form.controls.email.errors.required).toBeTruthy();
+ });
+ });
+
+ it('Email invalid when used wrong domain', () => {
+ fixture.whenStable().then( () => {
+ component.form.controls['email'].setValue('xyzqw@yopmail.com');
+ fixture.detectChanges();
+ fixture.whenStable().then( () => {
+ fixture.detectChanges();
+ expect(component.form.controls.email.errors.required).toBeFalsy();
+ expect(component.form.controls.email.errors.validateEmail).toBeTruthy();
+ });
+ });
+ });
+
+ it('form valid when completely filled', () => {
+ fixture.whenStable().then( () => {
+ component.form.controls['email'].setValue('xyzqw@gmail.com');
+ component.form.controls['password'].setValue('Qwertyui9!');
+ fixture.detectChanges();
+ fixture.whenStable().then( () => {
+ fixture.detectChanges();
+ expect(component.form.valid).toBeTruthy();
+ });
+ });
+ });
+});
diff --git a/src/app/directives/updateonhover.directive.spec.ts b/src/app/directives/updateonhover.directive.spec.ts
new file mode 100644
index 0000000..dc1109f
--- /dev/null
+++ b/src/app/directives/updateonhover.directive.spec.ts
@@ -0,0 +1,52 @@
+import { TestBed, ComponentFixture } from '@angular/core/testing';
+import { Component, DebugElement } from "@angular/core";
+import { By } from "@angular/platform-browser";
+import { UpdateOnHoverDirective } from './updateonhover.directive';
+
+@Component({
+ template:
+ `
+ `
+})
+class TestHoverComponent {
+}
+
+
+describe('Directive: Hover', () => {
+
+ let component: TestHoverComponent;
+ let fixture: ComponentFixture;
+ let element1: DebugElement;
+ let element2: DebugElement;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestHoverComponent, UpdateOnHoverDirective]
+ });
+ fixture = TestBed.createComponent(TestHoverComponent);
+ component = fixture.componentInstance;
+ element1 = fixture.debugElement.query(By.css('#button1'));
+ element2 = fixture.debugElement.query(By.css('#button2'));
+ fixture.detectChanges();
+ });
+
+ it('hovering over button 1', () => {
+ element1.triggerEventHandler('mouseover', null);
+ fixture.detectChanges();
+ expect(element1.nativeElement.style.backgroundColor).toBe('green');
+
+ element1.triggerEventHandler('mouseout', null);
+ fixture.detectChanges();
+ expect(element1.nativeElement.style.backgroundColor).toBe('blue');
+ });
+
+ it('hovering over button 2', () => {
+ element2.triggerEventHandler('mouseover', null);
+ fixture.detectChanges();
+ expect(element2.nativeElement.style.backgroundColor).toBe('green');
+
+ element2.triggerEventHandler('mouseout', null);
+ fixture.detectChanges();
+ expect(element2.nativeElement.style.backgroundColor).toBe('yellow');
+ });
+});
\ No newline at end of file
diff --git a/src/app/directives/updateonhover.directive.ts b/src/app/directives/updateonhover.directive.ts
new file mode 100644
index 0000000..2dc16b1
--- /dev/null
+++ b/src/app/directives/updateonhover.directive.ts
@@ -0,0 +1,27 @@
+import { Directive, HostListener, HostBinding, Input } from '@angular/core';
+
+@Directive({
+ selector: '[hover]'
+})
+export class UpdateOnHoverDirective {
+
+ @Input() defaultColor: string
+
+ @HostBinding("style.background-color") backgroundColor: string;
+
+ @HostListener('mouseover') onHover() {
+ this.backgroundColor = 'green';
+ }
+
+ @HostListener('mouseout') onLeave() {
+ this.backgroundColor = this.defaultColor || 'blue';
+ }
+
+ ngOnInit() {
+ if (this.defaultColor) {
+ this.backgroundColor = this.defaultColor
+ } else {
+ this.backgroundColor = 'blue';
+ }
+ }
+}
\ No newline at end of file