diff --git a/projects/aca-content/src/lib/components/search/search-results-row/search-results-row.component.spec.ts b/projects/aca-content/src/lib/components/search/search-results-row/search-results-row.component.spec.ts index 7e5d0c180..146c1c372 100644 --- a/projects/aca-content/src/lib/components/search/search-results-row/search-results-row.component.spec.ts +++ b/projects/aca-content/src/lib/components/search/search-results-row/search-results-row.component.spec.ts @@ -133,8 +133,82 @@ describe('SearchResultsRowComponent', () => { it('should pass node to badge component', () => { component.context = { row: { node: nodeEntry } }; + fixture.detectChanges(); + const badgeElement = fixture.debugElement.query(By.css('aca-datatable-cell-badges')); expect(badgeElement).not.toBe(null); - expect(badgeElement.componentInstance.node).toBe(component.context.node); + expect(badgeElement.componentInstance.node).toBe(component.context.row.node); + }); + + it('should escape plain < and > in values', (done) => { + const customEntry: ResultSetRowEntry = { + entry: { + ...nodeEntry.entry, + name: '2 < 5 > 3', + search: { score: 5 } + } + } as ResultSetRowEntry; + + component.context = { row: { node: customEntry } }; + component.name$ + .asObservable() + .pipe(first()) + .subscribe(() => { + fixture.detectChanges(); + + const nameElement: HTMLSpanElement = fixture.debugElement.query(By.css('.aca-link.aca-crop-text')).nativeElement; + expect(nameElement.innerHTML).toBe('2 < 5 > 3'); + expect(nameElement.textContent).toBe('2 < 5 > 3'); + done(); + }); + fixture.detectChanges(); + }); + + it('should not render script tags as HTML', (done) => { + const customEntry: ResultSetRowEntry = { + entry: { + ...nodeEntry.entry, + name: '', + search: { score: 5 } + } + } as ResultSetRowEntry; + + component.context = { row: { node: customEntry } }; + component.name$ + .asObservable() + .pipe(first()) + .subscribe(() => { + fixture.detectChanges(); + + const nameElement: HTMLSpanElement = fixture.debugElement.query(By.css('.aca-link.aca-crop-text')).nativeElement; + expect(nameElement.innerHTML).toContain('<script>alert("xss")</script>'); + expect(nameElement.textContent).toBe(''); + done(); + }); + fixture.detectChanges(); + }); + + it('should allow highlight spans but escape other tags', (done) => { + const customEntry: ResultSetRowEntry = { + entry: { + ...nodeEntry.entry, + name: 'BoldHighlight', + search: { score: 5 } + } + } as ResultSetRowEntry; + + component.context = { row: { node: customEntry } }; + component.name$ + .asObservable() + .pipe(first()) + .subscribe(() => { + fixture.detectChanges(); + + const nameElement: HTMLSpanElement = fixture.debugElement.query(By.css('.aca-link.aca-crop-text')).nativeElement; + expect(nameElement.innerHTML).toBe('<b>BoldHighlight</b>'); + expect(nameElement.textContent).toBe('BoldHighlight'); + done(); + }); + fixture.detectChanges(); }); });