1- import { batched , EventBus , markup } from "../src/runtime/utils" ;
1+ import { batched , EventBus , htmlEscape , markup } from "../src/runtime/utils" ;
22import { nextMicroTick } from "./helpers" ;
33
44describe ( "event bus behaviour" , ( ) => {
@@ -78,6 +78,61 @@ describe("markup", () => {
7878 const html = markup ( "<blink>Hello</blink>" ) ;
7979 expect ( html ) . toBeInstanceOf ( Markup ) ;
8080 } ) ;
81+ describe ( "htmlEscape" , ( ) => {
82+ test ( "htmlEscape escapes text" , ( ) => {
83+ const res = htmlEscape ( "<p>test</p>" ) ;
84+ expect ( res . toString ( ) ) . toBe ( "<p>test</p>" ) ;
85+ expect ( res ) . toBeInstanceOf ( Markup ) ;
86+ } ) ;
87+ test ( "htmlEscape keeps html markup" , ( ) => {
88+ const res = htmlEscape ( markup ( "<p>test</p>" ) ) ;
89+ expect ( res . toString ( ) ) . toBe ( "<p>test</p>" ) ;
90+ expect ( res ) . toBeInstanceOf ( Markup ) ;
91+ } ) ;
92+ test ( "htmlEscape produces empty string on undefined" , ( ) => {
93+ const res = htmlEscape ( undefined ) ;
94+ expect ( res . toString ( ) ) . toBe ( "" ) ;
95+ expect ( res ) . toBeInstanceOf ( Markup ) ;
96+ } ) ;
97+ test ( "htmlEscape produces string from number" , ( ) => {
98+ const res = htmlEscape ( 10 ) ;
99+ expect ( res . toString ( ) ) . toBe ( "10" ) ;
100+ expect ( res ) . toBeInstanceOf ( Markup ) ;
101+ } ) ;
102+ test ( "htmlEscape produces string from boolean" , ( ) => {
103+ const res = htmlEscape ( false ) ;
104+ expect ( res . toString ( ) ) . toBe ( "false" ) ;
105+ expect ( res ) . toBeInstanceOf ( Markup ) ;
106+ } ) ;
107+ test ( "htmlEscape correctly escapes various links" , ( ) => {
108+ expect ( htmlEscape ( "<a>this is a link</a>" ) . toString ( ) ) . toBe (
109+ "<a>this is a link</a>"
110+ ) ;
111+ expect ( htmlEscape ( `<a href="https://www.odoo.com">odoo<a>` ) . toString ( ) ) . toBe (
112+ `<a href="https://www.odoo.com">odoo<a>`
113+ ) ;
114+ expect ( htmlEscape ( `<a href='https://www.odoo.com'>odoo<a>` ) . toString ( ) ) . toBe (
115+ `<a href='https://www.odoo.com'>odoo<a>`
116+ ) ;
117+ expect ( htmlEscape ( "<a href='https://www.odoo.com'>Odoo`s website<a>" ) . toString ( ) ) . toBe (
118+ `<a href='https://www.odoo.com'>Odoo`s website<a>`
119+ ) ;
120+ } ) ;
121+ test ( "htmlEscape doesn't escape already escaped content" , ( ) => {
122+ const res = htmlEscape ( "<p>test</p>" ) ;
123+ expect ( res . toString ( ) ) . toBe ( "<p>test</p>" ) ;
124+ expect ( res ) . toBeInstanceOf ( Markup ) ;
125+ const res2 = htmlEscape ( res ) ;
126+ expect ( res2 . toString ( ) ) . toBe ( "<p>test</p>" ) ;
127+ expect ( res2 ) . toBeInstanceOf ( Markup ) ;
128+ expect ( res2 ) . toBe ( res ) ;
129+ } ) ;
130+ test ( "htmlEscape returns markup even for only-safe text" , ( ) => {
131+ const res = htmlEscape ( "safe" ) ;
132+ expect ( res . toString ( ) ) . toBe ( "safe" ) ;
133+ expect ( res ) . toBeInstanceOf ( Markup ) ;
134+ } ) ;
135+ } ) ;
81136 describe ( "tag function" , ( ) => {
82137 test ( "interpolated values are escaped" , ( ) => {
83138 const maliciousInput = "<script>alert('💥💥')</script>" ;
@@ -99,5 +154,11 @@ describe("markup", () => {
99154 const html = markup `<img src="${ imgUrl } ">` ;
100155 expect ( html . toString ( ) ) . toBe ( `<img src="lol" onerror="alert('xss')">` ) ;
101156 } ) ;
157+ test ( "already escaped content is not escaped again" , ( ) => {
158+ const res = htmlEscape ( "<p>test</p>" ) ;
159+ expect ( res . toString ( ) ) . toBe ( "<p>test</p>" ) ;
160+ const html = markup `${ res } ` ;
161+ expect ( html . toString ( ) ) . toBe ( "<p>test</p>" ) ;
162+ } ) ;
102163 } ) ;
103164} ) ;
0 commit comments