Angular2 - Expected safevalue must use [property] = binding

13,881

Solution 1

sanitizer.bypassSecurityTrustResourceUrl method returns SafeResourceUrlImpl class and you can't convert it to string (jasmine is trying to convert it internally).

abstract class SafeValueImpl implements SafeValue {
  constructor(public changingThisBreaksApplicationSecurity: string) {
    // empty
  }

  abstract getTypeName(): string;

  toString() {
    return `SafeValue must use [property]=binding: ${this.changingThisBreaksApplicationSecurity}` +
        ` (see http://g.co/ng/security#xss)`;
  }
}

You should use DomSanitizer.sanitize method instead (Angular uses it when applies property like [url]="value | safe")

it('should transform', () => {
  const safeResourceUrl = pipe.transform("Cross <script>alert('Hello')</script>");
  const sanitizedValue = sanitizer.sanitize(SecurityContext.RESOURCE_URL, safeResourceUrl);

  expect(sanitizedValue).toBe("Cross <script>alert('Hello')</script>");
});

PS. Here I assume you have typo in toBe statement, and that you are expecting string will save script tags.

Complete example you can find in Plunker

Solution 2

A slight variation on the accepted answer: compare the SafeValue output of your pipe to the sanitised expected value:

import { RichtextPipe } from './richtext.pipe';
import {BrowserModule, DomSanitizer} from "@angular/platform-browser";
import {TestBed} from "@angular/core/testing";

describe('RichtextPipe', () => {
  let domSanitizer: DomSanitizer;
  let pipe: RichtextPipe;

  beforeEach(() => {
    TestBed
      .configureTestingModule({
        imports: [
          BrowserModule
        ]
      });
    domSanitizer = TestBed.get(DomSanitizer);
    pipe = new RichtextPipe(domSanitizer);
  });

  it('should convert EventPage page link', () => {
    // Setup
    const html = '<a id="1" linktype="page" pagetype="EventPage">foo</a>';

    // Test
    const result = pipe.transform(html); 

    // Assert
    const expected = domSanitizer.bypassSecurityTrustHtml('<a routerLink="/events/1">foo</a>');
    expect(result).toEqual(expected);
  });


});

In this example, the RichtextPipe uses bypassSecurityTrustHtml to transform the output. If your pipe uses a different bypass method then you probably should use the same method on the expected value.

Share:
13,881
user3520629
Author by

user3520629

Updated on June 26, 2022

Comments

  • user3520629
    user3520629 almost 2 years

    I am writing a test for a SafePipe. The method uses bypassSecurityTrustResourceUrl() . I searched the available solutions and tried them but unfortunately, it didn't help me. The error is

    Expected SafeValue must use [property]=binding: Cross (see http://g.co/ng/security#xss) to be 'Cross site Request'.

    What's wrong I am doing here?

    import {Pipe, PipeTransform} from "@angular/core";
    import {DomSanitizer} from "@angular/platform-browser";
    
    @Pipe({name: 'safe'})
     export class SafePipe implements PipeTransform {
      constructor(private sanitizer: DomSanitizer) {
     }
    
     public transform(url: string): any {
       return this.sanitizer.bypassSecurityTrustResourceUrl(url);
     }
    }
    

    Test is:

    import {SafePipe} from './safe.pipe';
    import {DomSanitizer} from "@angular/platform-browser";
    import {DomSanitizerImpl} from "@angular/platform-browse/src/security/dom_sanitization_service";
    
    fdescribe('SafePipe', () => {
      let pipe: SafePipe;
      let sanitizer: DomSanitizer = new DomSanitizerImpl();
      beforeEach(() => {
        pipe = new SafePipe(sanitizer);
      });
    
      it('should transform', () => {
        expect(pipe.transform("Cross <script>alert('Hello')</script>")).toBe("Cross alert('Hello')");
      });
    });