safestyle_test.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright 2014 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Unit tests for goog.html.SafeStyle and its builders.
  16. */
  17. goog.provide('goog.html.safeStyleTest');
  18. goog.require('goog.html.SafeStyle');
  19. goog.require('goog.html.SafeUrl');
  20. goog.require('goog.object');
  21. goog.require('goog.string.Const');
  22. goog.require('goog.testing.jsunit');
  23. goog.setTestOnly('goog.html.safeStyleTest');
  24. function testSafeStyle() {
  25. var style = 'width: 1em;height: 1em;';
  26. var safeStyle =
  27. goog.html.SafeStyle.fromConstant(goog.string.Const.from(style));
  28. var extracted = goog.html.SafeStyle.unwrap(safeStyle);
  29. assertEquals(style, extracted);
  30. assertEquals(style, safeStyle.getTypedStringValue());
  31. assertEquals('SafeStyle{' + style + '}', String(safeStyle));
  32. // Interface marker is present.
  33. assertTrue(safeStyle.implementsGoogStringTypedString);
  34. }
  35. /** @suppress {checkTypes} */
  36. function testUnwrap() {
  37. var privateFieldName = 'privateDoNotAccessOrElseSafeStyleWrappedValue_';
  38. var markerFieldName = 'SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_';
  39. var propNames = goog.object.getKeys(
  40. goog.html.SafeStyle.fromConstant(goog.string.Const.from('')));
  41. assertContains(privateFieldName, propNames);
  42. assertContains(markerFieldName, propNames);
  43. var evil = {};
  44. evil[privateFieldName] = 'width: expression(evil);';
  45. evil[markerFieldName] = {};
  46. var exception =
  47. assertThrows(function() { goog.html.SafeStyle.unwrap(evil); });
  48. assertContains('expected object of type SafeStyle', exception.message);
  49. }
  50. function testFromConstant_allowsEmptyString() {
  51. assertEquals(
  52. goog.html.SafeStyle.EMPTY,
  53. goog.html.SafeStyle.fromConstant(goog.string.Const.from('')));
  54. }
  55. function testFromConstant_throwsOnForbiddenCharacters() {
  56. assertThrows(function() {
  57. goog.html.SafeStyle.fromConstant(goog.string.Const.from('width: x<;'));
  58. });
  59. assertThrows(function() {
  60. goog.html.SafeStyle.fromConstant(goog.string.Const.from('width: x>;'));
  61. });
  62. }
  63. function testFromConstant_throwsIfNoFinalSemicolon() {
  64. assertThrows(function() {
  65. goog.html.SafeStyle.fromConstant(goog.string.Const.from('width: 1em'));
  66. });
  67. }
  68. function testFromConstant_throwsIfNoColon() {
  69. assertThrows(function() {
  70. goog.html.SafeStyle.fromConstant(goog.string.Const.from('width= 1em;'));
  71. });
  72. }
  73. function testEmpty() {
  74. assertEquals('', goog.html.SafeStyle.unwrap(goog.html.SafeStyle.EMPTY));
  75. }
  76. function testCreate() {
  77. assertCreateEquals(
  78. 'background:url(i.png);margin:0;',
  79. {'background': goog.string.Const.from('url(i.png)'), 'margin': '0'});
  80. }
  81. function testCreate_allowsEmpty() {
  82. assertEquals(goog.html.SafeStyle.EMPTY, goog.html.SafeStyle.create({}));
  83. }
  84. function testCreate_skipsNull() {
  85. var style = goog.html.SafeStyle.create({'background': null});
  86. assertEquals(goog.html.SafeStyle.EMPTY, style);
  87. }
  88. function testCreate_allowsLengths() {
  89. assertCreateEquals(
  90. 'padding:0 1px .2% 3.4em;', // expected
  91. {'padding': '0 1px .2% 3.4em'});
  92. }
  93. function testCreate_allowsRgb() {
  94. assertCreateEquals(
  95. 'color:rgb(10,20,30);', // expected
  96. {'color': 'rgb(10,20,30)'});
  97. assertCreateEquals(
  98. 'color:rgb(10%, 20%, 30%);', // expected
  99. {'color': 'rgb(10%, 20%, 30%)'});
  100. }
  101. function testCreate_allowsRgba() {
  102. assertCreateEquals(
  103. 'color:rgba(10,20,30,0.1);', // expected
  104. {'color': 'rgba(10,20,30,0.1)'});
  105. assertCreateEquals(
  106. 'color:rgba(10%, 20%, 30%, .5);', // expected
  107. {'color': 'rgba(10%, 20%, 30%, .5)'});
  108. }
  109. function testCreate_allowsScale() {
  110. assertCreateEquals(
  111. 'transform:scale(.5, 2);', // expected
  112. {'transform': 'scale(.5, 2)'});
  113. }
  114. function testCreate_allowsRotate() {
  115. assertCreateEquals(
  116. 'transform:rotate(45deg);', // expected
  117. {'transform': 'rotate(45deg)'});
  118. }
  119. function testCreate_allowsTranslate() {
  120. assertCreateEquals(
  121. 'transform:translate(10px);', // expected
  122. {'transform': 'translate(10px)'});
  123. assertCreateEquals(
  124. 'transform:translateX(5px);', // expected
  125. {'transform': 'translateX(5px)'});
  126. }
  127. function testCreate_allowsUrl() {
  128. assertCreateEquals(
  129. 'background:url(http://example.com);',
  130. {'background': 'url(http://example.com)'});
  131. assertCreateEquals(
  132. 'background:url("http://example.com");',
  133. {'background': 'url("http://example.com")'});
  134. assertCreateEquals(
  135. 'background:url( \'http://example.com\' );',
  136. {'background': 'url( \'http://example.com\' )'});
  137. assertCreateEquals(
  138. 'background:url(http://example.com) red;',
  139. {'background': 'url(http://example.com) red'});
  140. assertCreateEquals(
  141. 'background:url(' + goog.html.SafeUrl.INNOCUOUS_STRING + ');',
  142. {'background': 'url(javascript:alert)'});
  143. assertCreateEquals(
  144. 'background:url(")");', // Expected.
  145. {'background': 'url(")")'});
  146. assertCreateEquals(
  147. 'background:url(" ");', // Expected.
  148. {'background': 'url(" ")'});
  149. assertThrows(function() {
  150. goog.html.SafeStyle.create({'background': 'url(\'http://example.com\'"")'});
  151. });
  152. assertThrows(function() {
  153. goog.html.SafeStyle.create({'background': 'url("\\\\")'});
  154. });
  155. assertThrows(function() {
  156. goog.html.SafeStyle.create({'background': 'url(a""b)'});
  157. });
  158. }
  159. function testCreate_throwsOnForbiddenCharacters() {
  160. assertThrows(function() { goog.html.SafeStyle.create({'<': '0'}); });
  161. assertThrows(function() {
  162. goog.html.SafeStyle.create({'color': goog.string.Const.from('<')});
  163. });
  164. }
  165. function testCreate_values() {
  166. var valids = [
  167. '0', '0 0', '1px', '100%', '2.3px', '.1em', 'red', '#f00', 'red !important',
  168. '"Times New Roman"', "'Times New Roman'", '"Bold \'nuff"',
  169. '"O\'Connor\'s Revenge"'
  170. ];
  171. for (var i = 0; i < valids.length; i++) {
  172. var value = valids[i];
  173. assertCreateEquals(
  174. 'background:' + value + ';', // expected
  175. {'background': value});
  176. }
  177. var invalids = [
  178. '', 'expression(alert(1))', '"', '"\'"\'', goog.string.Const.from('red;')
  179. ];
  180. for (var i = 0; i < invalids.length; i++) {
  181. var value = invalids[i];
  182. assertThrows(function() {
  183. goog.html.SafeStyle.create({'background': value});
  184. });
  185. }
  186. }
  187. /**
  188. * Asserts that created SafeStyle matches expected value.
  189. * @param {string} expected
  190. * @param {!goog.html.SafeStyle.PropertyMap} style
  191. */
  192. function assertCreateEquals(expected, style) {
  193. var style = goog.html.SafeStyle.create(style);
  194. assertEquals(expected, goog.html.SafeStyle.unwrap(style));
  195. }
  196. function testConcat() {
  197. var width =
  198. goog.html.SafeStyle.fromConstant(goog.string.Const.from('width: 1em;'));
  199. var margin = goog.html.SafeStyle.create({'margin': '0'});
  200. var padding = goog.html.SafeStyle.create({'padding': '0'});
  201. var style = goog.html.SafeStyle.concat(width, margin);
  202. assertEquals('width: 1em;margin:0;', goog.html.SafeStyle.unwrap(style));
  203. style = goog.html.SafeStyle.concat([width, margin]);
  204. assertEquals('width: 1em;margin:0;', goog.html.SafeStyle.unwrap(style));
  205. style = goog.html.SafeStyle.concat([width], [padding, margin]);
  206. assertEquals(
  207. 'width: 1em;padding:0;margin:0;', goog.html.SafeStyle.unwrap(style));
  208. }
  209. function testConcat_allowsEmpty() {
  210. var empty = goog.html.SafeStyle.EMPTY;
  211. assertEquals(empty, goog.html.SafeStyle.concat());
  212. assertEquals(empty, goog.html.SafeStyle.concat([]));
  213. assertEquals(empty, goog.html.SafeStyle.concat(empty));
  214. }