97732 Completed ContextHelpWrapper tests

This commit is contained in:
Koen Pauwels
2023-01-13 15:45:54 +01:00
parent 84c8b7690a
commit 6bee69bc3f
2 changed files with 75 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { of as observableOf, Observable, BehaviorSubject } from 'rxjs';
import { of as observableOf, BehaviorSubject } from 'rxjs';
import { ContextHelpWrapperComponent } from './context-help-wrapper.component';
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
import { TranslateService } from '@ngx-translate/core';
@@ -20,6 +20,7 @@ import { By } from '@angular/platform-browser';
[id]="id"
[tooltipPlacement]="tooltipPlacement"
[iconPlacement]="iconPlacement"
[dontParseLinks]="dontParseLinks"
>
</ds-context-help-wrapper>
`
@@ -29,11 +30,12 @@ class TemplateComponent {
@Input() id: string;
@Input() tooltipPlacement?: PlacementArray;
@Input() iconPlacement?: PlacementDir;
@Input() dontParseLinks?: boolean;
}
const messages = {
lorem: 'lorem ipsum dolor sit amet',
linkTest: 'This is text, [this](https://dspace.lyrasis.org) is a link, and [so is this](https://google.com)'
linkTest: 'This is text, [this](https://dspace.lyrasis.org/) is a link, and [so is this](https://google.com/)'
};
const exampleContextHelp: ContextHelp = {
id: 'test-tooltip',
@@ -147,6 +149,55 @@ describe('ContextHelpWrapperComponent', () => {
fixture.detectChanges();
expect(wrapperComponent.tooltip.open).toHaveBeenCalled();
expect(wrapperComponent.tooltip.close).toHaveBeenCalledTimes(0);
expect(fixture.debugElement.query(By.css('.ds-context-help-content')).nativeElement.textContent)
.toMatch(/\s*lorem ipsum dolor sit amet\s*/);
});
it('should correctly display links', () => {
templateComponent.content = 'linkTest';
getContextHelp$.next({...exampleContextHelp, isTooltipVisible: true});
fixture.detectChanges();
const nodeList: NodeList = fixture.debugElement.query(By.css('.ds-context-help-content'))
.nativeElement
.childNodes;
const relevantNodes = Array.from(nodeList).filter(node => node.nodeType != Node.COMMENT_NODE);
expect(relevantNodes.length).toBe(4);
const [text1, link1, text2, link2] = relevantNodes;
expect(text1.nodeType).toBe(Node.TEXT_NODE);
expect(text1.nodeValue).toMatch(/\s* This is text, \s*/);
expect(link1.nodeName).toBe('A');
expect((link1 as any).href).toBe('https://dspace.lyrasis.org/');
expect(link1.textContent).toBe('this');
expect(text2.nodeType).toBe(Node.TEXT_NODE);
expect(text2.nodeValue).toMatch(/\s* is a link, and \s*/);
expect(link2.nodeName).toBe('A');
expect((link2 as any).href).toBe('https://google.com/');
expect(link2.textContent).toBe('so is this');
});
it('should not display links if specified not to', () => {
templateComponent.dontParseLinks = true;
templateComponent.content = 'linkTest';
getContextHelp$.next({...exampleContextHelp, isTooltipVisible: true});
fixture.detectChanges();
const nodeList: NodeList = fixture.debugElement.query(By.css('.ds-context-help-content'))
.nativeElement
.childNodes;
const relevantNodes = Array.from(nodeList).filter(node => node.nodeType != Node.COMMENT_NODE);
expect(relevantNodes.length).toBe(1);
const [text] = relevantNodes;
expect(text.nodeType).toBe(Node.TEXT_NODE);
expect(text.nodeValue).toMatch(
/\s* This is text, \[this\]\(https:\/\/dspace.lyrasis.org\/\) is a link, and \[so is this\]\(https:\/\/google.com\/\) \s*/);
});
describe('after the icon is clicked again', () => {
@@ -165,6 +216,4 @@ describe('ContextHelpWrapperComponent', () => {
});
});
});
// TODO: link parsing tests
});

View File

@@ -1,8 +1,8 @@
import { Component, Input, OnInit, TemplateRef, OnDestroy, AfterViewInit, ViewChild } from '@angular/core';
import { PlacementArray } from '@ng-bootstrap/ng-bootstrap/util/positioning';
import { TranslateService } from '@ngx-translate/core';
import { Observable, of as observableOf, Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, Subscription, BehaviorSubject, combineLatest } from 'rxjs';
import { map, distinctUntilChanged, mergeMap } from 'rxjs/operators';
import { PlacementDir } from './placement-dir.model';
import content from '*.scss';
import { ContextHelpService } from '../context-help.service';
@@ -10,6 +10,8 @@ import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
import { hasValueOperator } from '../empty.util';
import { ContextHelp } from '../context-help.model';
type ParsedContent = (string | {href: string, text: string})[];
/**
* This component renders an info icon next to the wrapped element which
* produces a tooltip when clicked.
@@ -44,21 +46,21 @@ export class ContextHelpWrapperComponent implements OnInit, OnDestroy {
/**
* If true, don't process text to render links.
*/
@Input() dontParseLinks?: boolean;
@Input() set dontParseLinks(dont: boolean) {
this.dontParseLinks$.next(dont);
}
private dontParseLinks$: BehaviorSubject<boolean> = new BehaviorSubject(false);
shouldShowIcon$: Observable<boolean>;
tooltip: NgbTooltip;
// TODO: dependent on evaluation order of input setters?
parsedContent$: Observable<(string | {href: string, text: string})[]> = observableOf([]);
@Input() set content(content : string) {
this.parsedContent$ = this.translateService.get(content).pipe(
map(this.dontParseLinks
? ((text: string) => [text])
: this.parseLinks)
);
this.content$.next(content);
}
private content$: BehaviorSubject<string | undefined> = new BehaviorSubject(undefined);
parsedContent$: Observable<ParsedContent>;
private subs: {always: Subscription[], tooltipBound: Subscription[]}
= {always: [], tooltipBound: []};
@@ -69,8 +71,15 @@ export class ContextHelpWrapperComponent implements OnInit, OnDestroy {
) { }
ngOnInit() {
this.parsedContent$ = combineLatest([
this.content$.pipe(distinctUntilChanged(), mergeMap(content => this.translateService.get(content))),
this.dontParseLinks$.pipe(distinctUntilChanged())
]).pipe(
map(([content, dontParseLinks]) =>
dontParseLinks ? [content] : this.parseLinks(content))
);
this.shouldShowIcon$ = this.contextHelpService.shouldShowIcons$();
this.subs.always = [this.shouldShowIcon$.subscribe()];
this.subs.always = [this.parsedContent$.subscribe(), this.shouldShowIcon$.subscribe()];
}
@ViewChild('tooltip', { static: false }) set setTooltip(tooltip: NgbTooltip) {
@@ -127,8 +136,8 @@ export class ContextHelpWrapperComponent implements OnInit, OnDestroy {
* {href: "https://youtube.com", text: "so is this"}
* ]
*/
private parseLinks(content: string): (string | {href: string, text: string})[] {
// Implementation note: due to unavailability of `matchAll` method on strings,
private parseLinks(content: string): ParsedContent {
// Implementation note: due to `matchAll` method on strings not being available for all versions,
// separate "split" and "parse" steps are needed.
// We use splitRegexp (the outer `match` call) to split the text