fix(aio): correctly intercept links with LinkDirective
This commit is contained in:
parent
fe962f6de7
commit
5815983178
|
@ -1,7 +1,93 @@
|
|||
import { async, inject, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { Component } from '@angular/core';
|
||||
import { LocationService } from 'app/shared/location.service';
|
||||
import { MockLocationService } from 'testing/location.service';
|
||||
import { LinkDirective } from './link.directive';
|
||||
|
||||
xdescribe('LinkDirective', () => {
|
||||
it('should attach to all anchor elements', () => {});
|
||||
it('should bind a property to the "href" attribute', () => {});
|
||||
it('should intercept clicks on the element and call `location.go()`', () => {});
|
||||
describe('LinkDirective', () => {
|
||||
|
||||
@Component({
|
||||
template: '<a href="{{ url }}">Test Link</a>'
|
||||
})
|
||||
class TestComponent {
|
||||
url: string;
|
||||
}
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
LinkDirective,
|
||||
TestComponent
|
||||
],
|
||||
providers: [
|
||||
{ provide: LocationService, useFactory: () => new MockLocationService('initial/url') }
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
it('should attach to all anchor elements', () => {
|
||||
const fixture = TestBed.createComponent(TestComponent);
|
||||
const directiveElement = fixture.debugElement.query(By.directive(LinkDirective));
|
||||
expect(directiveElement.name).toEqual('a');
|
||||
});
|
||||
|
||||
it('should bind a property to the "href" attribute', () => {
|
||||
const fixture = TestBed.createComponent(TestComponent);
|
||||
const directiveElement = fixture.debugElement.query(By.directive(LinkDirective));
|
||||
|
||||
fixture.componentInstance.url = 'test/url';
|
||||
fixture.detectChanges();
|
||||
expect(directiveElement.properties['href']).toEqual('test/url');
|
||||
});
|
||||
|
||||
it('should set the "target" attribute to "_blank" if the href is absolute, otherwise "_self"', () => {
|
||||
const fixture = TestBed.createComponent(TestComponent);
|
||||
const directiveElement = fixture.debugElement.query(By.directive(LinkDirective));
|
||||
|
||||
fixture.componentInstance.url = 'http://test/url';
|
||||
fixture.detectChanges();
|
||||
expect(directiveElement.properties['target']).toEqual('_blank');
|
||||
|
||||
fixture.componentInstance.url = 'https://test/url';
|
||||
fixture.detectChanges();
|
||||
expect(directiveElement.properties['target']).toEqual('_blank');
|
||||
|
||||
fixture.componentInstance.url = 'ftp://test/url';
|
||||
fixture.detectChanges();
|
||||
expect(directiveElement.properties['target']).toEqual('_blank');
|
||||
|
||||
fixture.componentInstance.url = '//test/url';
|
||||
fixture.detectChanges();
|
||||
expect(directiveElement.properties['target']).toEqual('_blank');
|
||||
|
||||
fixture.componentInstance.url = 'test/url';
|
||||
fixture.detectChanges();
|
||||
expect(directiveElement.properties['target']).toEqual('_self');
|
||||
|
||||
fixture.componentInstance.url = '/test/url';
|
||||
fixture.detectChanges();
|
||||
expect(directiveElement.properties['target']).toEqual('_self');
|
||||
});
|
||||
|
||||
it('should intercept clicks for local urls and call `location.go()`', inject([LocationService], (location: LocationService) => {
|
||||
const fixture = TestBed.createComponent(TestComponent);
|
||||
const directiveElement = fixture.debugElement.query(By.directive(LinkDirective));
|
||||
fixture.componentInstance.url = 'some/local/url';
|
||||
fixture.detectChanges();
|
||||
location.go = jasmine.createSpy('Location.go');
|
||||
directiveElement.triggerEventHandler('click', null);
|
||||
expect(location.go).toHaveBeenCalledWith('some/local/url');
|
||||
}));
|
||||
|
||||
it('should not intercept clicks for absolute urls', inject([LocationService], (location: LocationService) => {
|
||||
const fixture = TestBed.createComponent(TestComponent);
|
||||
const directiveElement = fixture.debugElement.query(By.directive(LinkDirective));
|
||||
fixture.componentInstance.url = 'https://some/absolute/url';
|
||||
fixture.detectChanges();
|
||||
location.go = jasmine.createSpy('Location.go');
|
||||
directiveElement.triggerEventHandler('click', null);
|
||||
expect(location.go).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Directive, HostListener, HostBinding, Input } from '@angular/core';
|
||||
import { Directive, HostListener, HostBinding, Input, OnChanges } from '@angular/core';
|
||||
import { LocationService } from 'app/shared/location.service';
|
||||
@Directive({
|
||||
/* tslint:disable-next-line:directive-selector */
|
||||
selector: 'a[href]'
|
||||
})
|
||||
export class LinkDirective {
|
||||
export class LinkDirective implements OnChanges {
|
||||
|
||||
// We need both these decorators to ensure that we can access
|
||||
// the href programmatically, and that it appears as a real
|
||||
|
@ -13,11 +13,27 @@ export class LinkDirective {
|
|||
@HostBinding()
|
||||
href: string;
|
||||
|
||||
@HostBinding()
|
||||
target: string;
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
onClick($event) {
|
||||
if (this.isAbsolute(this.href)) {
|
||||
return true;
|
||||
} else {
|
||||
this.location.go(this.href);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private isAbsolute(url) {
|
||||
return /^[a-z]+:\/\/|\/\//i.test(url);
|
||||
}
|
||||
|
||||
constructor(private location: LocationService) { }
|
||||
|
||||
ngOnChanges() {
|
||||
this.target = this.isAbsolute(this.href) ? '_blank' : '_self';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue