diff --git a/src/app/shared/external-link/external-link.directive.spec.ts b/src/app/shared/external-link/external-link.directive.spec.ts
index 9044ee6c4..b7f815cd6 100644
--- a/src/app/shared/external-link/external-link.directive.spec.ts
+++ b/src/app/shared/external-link/external-link.directive.spec.ts
@@ -1,8 +1,162 @@
+import { Component, DebugElement } from '@angular/core';
+import { By } from '@angular/platform-browser';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
import { ExternalLinkDirective } from './external-link.directive';
+@Component({
+ template: `Link External
+
+
+ Link External Dynamic
+
+
+ Link Internal
+
+
+ Link Internal Dynamic
+
+
+ Link without href`
+})
+class TestExernalLinkComponent {
+ hostname = location.hostname;
+ dynamicInternalLink = this.hostname + '#anchor';
+ dynamicExternalLink = 'https://coryrylan.com/blog/managing-external-links-safely-in-angular';
+
+ doSomething() {
+ console.log('Clicked on link without href');
+ }
+}
+
describe('ExternalLinkDirective', () => {
- it('should create an instance', () => {
- const directive = new ExternalLinkDirective();
- expect(directive).toBeTruthy();
+ let component: TestExernalLinkComponent;
+ let fixture: ComponentFixture;
+
+ let aDes: DebugElement[];
+ let bareADes: DebugElement[];
+
+ const expectedExternalLink = 'https://coryrylan.com/blog/managing-external-links-safely-in-angular';
+ const expectedNewExternalLink = 'https://anton-webern.ch/';
+ const expectedInternalLink = '#anchor';
+ const expectedRelAttr = 'noopener noreferrer';
+ const expectedTargetAttr = '_blank';
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestExernalLinkComponent, ExternalLinkDirective]
+ });
+
+ fixture = TestBed.createComponent(TestExernalLinkComponent);
+ component = fixture.componentInstance;
+
+ fixture.detectChanges(); // initial binding
+ });
+
+ it('should have 4 anchor elements with href attributes', () => {
+ // all elements with an attached ExternalLinkDirective (a[href])
+ aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
+
+ expect(aDes.length).toBe(4, 'should be 4');
+
+ console.log(aDes);
+ });
+
+ it('should have 1 anchor element without href attributes', () => {
+ bareADes = fixture.debugElement.queryAll(By.css('a:not([href])'));
+
+ expect(bareADes.length).toBe(1, 'should be 1');
+ });
+
+ it('should apply [href|target|rel] values to 1st anchor element (external)', () => {
+ aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
+ const aEl = aDes[0].nativeElement;
+
+ expect(aEl.href).toBeTruthy();
+ expect(aEl.href).toBe(expectedExternalLink, `should be ${expectedExternalLink}`);
+
+ expect(aEl.rel).toBeTruthy();
+ expect(aEl.rel).toBe(expectedRelAttr, `should be ${expectedRelAttr}`);
+
+ expect(aEl.target).toBeTruthy();
+ expect(aEl.target).toBe(expectedTargetAttr, `should be ${expectedTargetAttr}`);
+
+ expect(aEl.innerText).toBe('Link External', 'should be "Link External"');
+ });
+
+ it('should apply [href|target|rel] values to 2nd anchor element (dynamic external)', () => {
+ aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
+ const aEl = aDes[1].nativeElement;
+
+ expect(aEl.href).toBeTruthy();
+ expect(aEl.href).toBe(expectedExternalLink, `should be ${expectedExternalLink}`);
+
+ expect(aEl.rel).toBeTruthy();
+ expect(aEl.rel).toBe(expectedRelAttr, `should be ${expectedRelAttr}`);
+
+ expect(aEl.target).toBeTruthy();
+ expect(aEl.target).toBe(expectedTargetAttr, `should be ${expectedTargetAttr}`);
+
+ expect(aEl.innerText).toBe('Link External Dynamic', 'should be "Link External Dynamic"');
+ });
+
+ it('should not apply [target|rel] values to 3rd anchor element (internal)', () => {
+ aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
+ const aEl = aDes[2].nativeElement;
+
+ const expectedHref = aEl.baseURI + aEl.hostname + expectedInternalLink;
+
+ expect(aEl.href).toBeTruthy();
+ expect(aEl.href).toBe(expectedHref, `should be ${expectedHref}`);
+
+ expect(aEl.rel).not.toBeTruthy('should be empty string');
+ expect(aEl.target).not.toBeTruthy('should be empty string');
+
+ expect(aEl.innerText).toBe('Link Internal', 'should be "Link Internal"');
+ });
+
+ it('should not apply [target|rel] values to 4th anchor element (dynamic internal)', () => {
+ aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
+ const aEl = aDes[3].nativeElement;
+
+ const expectedHref = aEl.baseURI + aEl.hostname + expectedInternalLink;
+
+ expect(aEl.href).toBeTruthy();
+ expect(aEl.href).toBe(expectedHref, `should be ${expectedHref}`);
+
+ expect(aEl.rel).not.toBeTruthy('should be empty string');
+ expect(aEl.target).not.toBeTruthy('should be empty string');
+
+ expect(aEl.innerText).toBe('Link Internal Dynamic', 'should be "Link Internal Dynamic"');
+ });
+
+ it('should not apply [href|target|rel] values to bare anchor', () => {
+ bareADes = fixture.debugElement.queryAll(By.css('a:not([href])'));
+
+ expect(bareADes[0].properties.href).not.toBeTruthy('should be empty string');
+ expect(bareADes[0].properties.target).not.toBeTruthy('should be empty string');
+ expect(bareADes[0].properties.rel).not.toBeTruthy('should be empty string');
+ expect(bareADes[0].properties.innerText).toBe('Link without href', 'should be "Link without href"');
+ });
+
+ it('should reflect input change for [href] values', () => {
+ component.dynamicExternalLink = expectedNewExternalLink;
+
+ // apply changes
+ fixture.detectChanges();
+
+ aDes = fixture.debugElement.queryAll(By.directive(ExternalLinkDirective));
+ const aEl = aDes[1].nativeElement;
+
+ expect(aEl.href).toBeTruthy();
+ expect(aEl.href).toBe(expectedNewExternalLink, `should be ${expectedNewExternalLink}`);
+
+ expect(aEl.rel).toBeTruthy();
+ expect(aEl.rel).toBe(expectedRelAttr, `should be ${expectedRelAttr}`);
+
+ expect(aEl.target).toBeTruthy();
+ expect(aEl.target).toBe(expectedTargetAttr, `should be ${expectedTargetAttr}`);
+
+ expect(aEl.innerText).toBe('Link External Dynamic', 'should be "Link External Dynamic"');
});
});
diff --git a/src/app/shared/external-link/external-link.directive.ts b/src/app/shared/external-link/external-link.directive.ts
index f42efa53f..798dc44ab 100644
--- a/src/app/shared/external-link/external-link.directive.ts
+++ b/src/app/shared/external-link/external-link.directive.ts
@@ -20,7 +20,6 @@ export class ExternalLinkDirective implements OnChanges {
this.targetAttr = '_blank';
this.relAttr = 'noopener noreferrer';
}
- console.log(this.hrefAttr);
}
private isExternalLink() {