trustedresourceurl_test.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright 2013 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.TrustedResourceUrl and its builders.
  16. */
  17. goog.provide('goog.html.trustedResourceUrlTest');
  18. goog.require('goog.html.TrustedResourceUrl');
  19. goog.require('goog.i18n.bidi.Dir');
  20. goog.require('goog.object');
  21. goog.require('goog.string.Const');
  22. goog.require('goog.testing.jsunit');
  23. goog.setTestOnly('goog.html.trustedResourceUrlTest');
  24. function testTrustedResourceUrl() {
  25. var url = 'javascript:trusted();';
  26. var trustedResourceUrl =
  27. goog.html.TrustedResourceUrl.fromConstant(goog.string.Const.from(url));
  28. var extracted = goog.html.TrustedResourceUrl.unwrap(trustedResourceUrl);
  29. assertEquals(url, extracted);
  30. assertEquals(url, trustedResourceUrl.getTypedStringValue());
  31. assertEquals(
  32. 'TrustedResourceUrl{javascript:trusted();}', String(trustedResourceUrl));
  33. // URLs are always LTR.
  34. assertEquals(goog.i18n.bidi.Dir.LTR, trustedResourceUrl.getDirection());
  35. // Interface markers are present.
  36. assertTrue(trustedResourceUrl.implementsGoogStringTypedString);
  37. assertTrue(trustedResourceUrl.implementsGoogI18nBidiDirectionalString);
  38. }
  39. function testFormat_validFormatString() {
  40. // With scheme.
  41. assertValidFormat(goog.string.Const.from('httpS://www.gOOgle.com/'));
  42. // Scheme-relative.
  43. assertValidFormat(goog.string.Const.from('//www.google.com/'));
  44. // Origin with hyphen and port.
  45. assertValidFormat(goog.string.Const.from('//ww-w.google.com:1000/path'));
  46. // IPv6 origin.
  47. assertValidFormat(goog.string.Const.from('//[::1]/path'));
  48. // Path-absolute.
  49. assertValidFormat(goog.string.Const.from('/path'));
  50. assertValidFormat(goog.string.Const.from('/path/x'));
  51. assertValidFormat(goog.string.Const.from('/path#x'));
  52. assertValidFormat(goog.string.Const.from('/path?x'));
  53. // Mixed case.
  54. assertValidFormat(goog.string.Const.from('httpS://www.google.cOm/pAth'));
  55. assertValidFormat(goog.string.Const.from('about:blank'));
  56. assertValidFormat(goog.string.Const.from('about:blank#x'));
  57. }
  58. /**
  59. * Asserts that format with no arguments is allowed and results in a URL
  60. * with itself.
  61. * @param {!goog.string.Const} format
  62. */
  63. function assertValidFormat(format) {
  64. var url = goog.html.TrustedResourceUrl.format(format, {});
  65. assertEquals(
  66. goog.string.Const.unwrap(format),
  67. goog.html.TrustedResourceUrl.unwrap(url));
  68. }
  69. function testFormat_args() {
  70. var url = goog.html.TrustedResourceUrl.format(
  71. goog.string.Const.from('/path/%{dir1}/%{dir2}?n1=v1%{opt_param}'), {
  72. 'dir1': 'd%/?#=',
  73. 'dir2': 2,
  74. 'opt_param': goog.string.Const.from('n2=v2%/?#=')
  75. });
  76. assertEquals(
  77. '/path/d%25%2F%3F%23%3D/2?n1=v1n2=v2%/?#=',
  78. goog.html.TrustedResourceUrl.unwrap(url));
  79. // Only \w is permitted inside %{...}.
  80. var url = goog.html.TrustedResourceUrl.format(
  81. goog.string.Const.from('/path/%{!%{label}}%{foo'), {'label': 'value'});
  82. assertEquals(
  83. '/path/%{!value}%{foo', goog.html.TrustedResourceUrl.unwrap(url));
  84. }
  85. function testFormat_missingArgs() {
  86. var exception = assertThrows(function() {
  87. goog.html.TrustedResourceUrl.format(
  88. goog.string.Const.from('https://www.google.com/path/%{arg1}'),
  89. {'arg2': 'irrelevant'});
  90. });
  91. assertContains('no valid label mapping found', exception.message);
  92. }
  93. function testFormat_invalidFormatString() {
  94. // Invalid scheme.
  95. assertInvalidFormat(goog.string.Const.from('ftp://'));
  96. // Missing origin.
  97. assertInvalidFormat(goog.string.Const.from('https://'));
  98. assertInvalidFormat(goog.string.Const.from('https:///'));
  99. assertInvalidFormat(goog.string.Const.from('//'));
  100. assertInvalidFormat(goog.string.Const.from('///'));
  101. // Missing / after origin.
  102. assertInvalidFormat(goog.string.Const.from('https://google.com'));
  103. // Invalid char in origin.
  104. assertInvalidFormat(goog.string.Const.from('https://www.google%.com/'));
  105. assertInvalidFormat(goog.string.Const.from('https://www.google\\.com/'));
  106. assertInvalidFormat(
  107. goog.string.Const.from('https://user:password@www.google.com/'));
  108. // Two slashes, would allow origin to be set dynamically.
  109. assertInvalidFormat(goog.string.Const.from('//'));
  110. // Two slashes. IE allowed (allows?) '\' instead of '/'.
  111. assertInvalidFormat(goog.string.Const.from('/\\'));
  112. // Relative path.
  113. assertInvalidFormat(goog.string.Const.from('abc'));
  114. assertInvalidFormat(goog.string.Const.from('about:blankX'));
  115. }
  116. /**
  117. * Asserts that format with no arguments throws.
  118. * @param {!goog.string.Const} format
  119. */
  120. function assertInvalidFormat(format) {
  121. var exception = assertThrows(goog.string.Const.unwrap(format), function() {
  122. goog.html.TrustedResourceUrl.format(format, {});
  123. });
  124. assertContains('Invalid TrustedResourceUrl format', exception.message);
  125. }
  126. function testFromConstants() {
  127. assertEquals('', goog.html.TrustedResourceUrl.unwrap(
  128. goog.html.TrustedResourceUrl.fromConstants([])));
  129. assertEquals('foo', goog.html.TrustedResourceUrl.unwrap(
  130. goog.html.TrustedResourceUrl.fromConstants([
  131. goog.string.Const.from('foo')
  132. ])));
  133. assertEquals('foobar', goog.html.TrustedResourceUrl.unwrap(
  134. goog.html.TrustedResourceUrl.fromConstants([
  135. goog.string.Const.from('foo'),
  136. goog.string.Const.from('bar')
  137. ])));
  138. }
  139. function testFormatWithParams() {
  140. var url = goog.html.TrustedResourceUrl.formatWithParams(
  141. goog.string.Const.from('https://example.com/'), {}, {'a': 'x'});
  142. assertEquals('https://example.com/?a=x', url.getTypedStringValue());
  143. url = goog.html.TrustedResourceUrl.formatWithParams(
  144. goog.string.Const.from('https://example.com/%{file}'), {'file': 'abc'},
  145. {'b': 1, 'c': null, 'd': undefined});
  146. assertEquals('https://example.com/abc?b=1', url.getTypedStringValue());
  147. }
  148. /** @suppress {checkTypes} */
  149. function testUnwrap() {
  150. var privateFieldName =
  151. 'privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_';
  152. var markerFieldName =
  153. 'TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_';
  154. var propNames = goog.object.getKeys(
  155. goog.html.TrustedResourceUrl.fromConstant(goog.string.Const.from('')));
  156. assertContains(privateFieldName, propNames);
  157. assertContains(markerFieldName, propNames);
  158. var evil = {};
  159. evil[privateFieldName] = 'http://example.com/evil.js';
  160. evil[markerFieldName] = {};
  161. var exception =
  162. assertThrows(function() { goog.html.TrustedResourceUrl.unwrap(evil); });
  163. assertContains(
  164. 'expected object of type TrustedResourceUrl', exception.message);
  165. }