string_test.js 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  1. // Copyright 2006 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.string.
  16. */
  17. /** @suppress {extraProvide} */
  18. goog.provide('goog.stringTest');
  19. goog.require('goog.dom');
  20. goog.require('goog.dom.TagName');
  21. goog.require('goog.functions');
  22. goog.require('goog.object');
  23. goog.require('goog.string');
  24. goog.require('goog.string.Unicode');
  25. goog.require('goog.testing.MockControl');
  26. goog.require('goog.testing.PropertyReplacer');
  27. goog.require('goog.testing.jsunit');
  28. goog.setTestOnly('goog.stringTest');
  29. var stubs;
  30. var mockControl;
  31. function setUp() {
  32. stubs = new goog.testing.PropertyReplacer();
  33. mockControl = new goog.testing.MockControl();
  34. }
  35. function tearDown() {
  36. stubs.reset();
  37. mockControl.$tearDown();
  38. }
  39. //=== tests for goog.string.collapseWhitespace ===
  40. function testCollapseWhiteSpace() {
  41. var f = goog.string.collapseWhitespace;
  42. assertEquals('Leading spaces not stripped', f(' abc'), 'abc');
  43. assertEquals('Trailing spaces not stripped', f('abc '), 'abc');
  44. assertEquals('Wrapping spaces not stripped', f(' abc '), 'abc');
  45. assertEquals(
  46. 'All white space chars not stripped', f('\xa0\n\t abc\xa0\n\t '), 'abc');
  47. assertEquals('Spaces not collapsed', f('a b c'), 'a b c');
  48. assertEquals('Tabs not collapsed', f('a\t\t\tb\tc'), 'a b c');
  49. assertEquals(
  50. 'All check failed', f(' \ta \t \t\tb\t\n\xa0 c \t\n'), 'a b c');
  51. }
  52. function testIsEmpty() {
  53. assertTrue(goog.string.isEmpty(''));
  54. assertTrue(goog.string.isEmpty(' '));
  55. assertTrue(goog.string.isEmpty(' '));
  56. assertTrue(goog.string.isEmpty(' \t\t\n\xa0 '));
  57. assertFalse(goog.string.isEmpty(' abc \t\xa0'));
  58. assertFalse(goog.string.isEmpty(' a b c \t'));
  59. assertFalse(goog.string.isEmpty(';'));
  60. assertFalse(goog.string.isEmpty(undefined));
  61. assertFalse(goog.string.isEmpty(null));
  62. assertFalse(goog.string.isEmpty({a: 1, b: 2}));
  63. }
  64. function testIsEmptyOrWhitespace() {
  65. assertTrue(goog.string.isEmptyOrWhitespace(''));
  66. assertTrue(goog.string.isEmptyOrWhitespace(' '));
  67. assertTrue(goog.string.isEmptyOrWhitespace(' '));
  68. assertTrue(goog.string.isEmptyOrWhitespace(' \t\t\n\xa0 '));
  69. assertFalse(goog.string.isEmptyOrWhitespace(' abc \t\xa0'));
  70. assertFalse(goog.string.isEmptyOrWhitespace(' a b c \t'));
  71. assertFalse(goog.string.isEmptyOrWhitespace(';'));
  72. assertFalse(goog.string.isEmptyOrWhitespace(undefined));
  73. assertFalse(goog.string.isEmptyOrWhitespace(null));
  74. assertFalse(goog.string.isEmptyOrWhitespace({a: 1, b: 2}));
  75. }
  76. function testIsEmptyString() {
  77. assertTrue(goog.string.isEmptyString(''));
  78. assertFalse(goog.string.isEmptyString(' '));
  79. assertFalse(goog.string.isEmptyString(' '));
  80. assertFalse(goog.string.isEmptyString(' \t\t\n\xa0 '));
  81. assertFalse(goog.string.isEmptyString(' abc \t\xa0'));
  82. assertFalse(goog.string.isEmptyString(' a b c \t'));
  83. assertFalse(goog.string.isEmptyString(';'));
  84. assertFalse(goog.string.isEmptyString({a: 1, b: 2}));
  85. }
  86. function testIsEmptySafe() {
  87. assertTrue(goog.string.isEmptySafe(''));
  88. assertTrue(goog.string.isEmptySafe(' '));
  89. assertTrue(goog.string.isEmptySafe(' '));
  90. assertTrue(goog.string.isEmptySafe(' \t\t\n\xa0 '));
  91. assertFalse(goog.string.isEmptySafe(' abc \t\xa0'));
  92. assertFalse(goog.string.isEmptySafe(' a b c \t'));
  93. assertFalse(goog.string.isEmptySafe(';'));
  94. assertTrue(goog.string.isEmptySafe(undefined));
  95. assertTrue(goog.string.isEmptySafe(null));
  96. assertFalse(goog.string.isEmptySafe({a: 1, b: 2}));
  97. }
  98. function testIsEmptyOrWhitespaceSafe() {
  99. assertTrue(goog.string.isEmptyOrWhitespaceSafe(''));
  100. assertTrue(goog.string.isEmptyOrWhitespaceSafe(' '));
  101. assertTrue(goog.string.isEmptyOrWhitespaceSafe(' '));
  102. assertTrue(goog.string.isEmptyOrWhitespaceSafe(' \t\t\n\xa0 '));
  103. assertFalse(goog.string.isEmptyOrWhitespaceSafe(' abc \t\xa0'));
  104. assertFalse(goog.string.isEmptyOrWhitespaceSafe(' a b c \t'));
  105. assertFalse(goog.string.isEmptyOrWhitespaceSafe(';'));
  106. assertTrue(goog.string.isEmptyOrWhitespaceSafe(undefined));
  107. assertTrue(goog.string.isEmptyOrWhitespaceSafe(null));
  108. assertFalse(goog.string.isEmptyOrWhitespaceSafe({a: 1, b: 2}));
  109. }
  110. //=== tests for goog.string.isAlpha ===
  111. function testIsAlpha() {
  112. assertTrue('"a" should be alpha', goog.string.isAlpha('a'));
  113. assertTrue('"n" should be alpha', goog.string.isAlpha('n'));
  114. assertTrue('"z" should be alpha', goog.string.isAlpha('z'));
  115. assertTrue('"A" should be alpha', goog.string.isAlpha('A'));
  116. assertTrue('"N" should be alpha', goog.string.isAlpha('N'));
  117. assertTrue('"Z" should be alpha', goog.string.isAlpha('Z'));
  118. assertTrue('"aa" should be alpha', goog.string.isAlpha('aa'));
  119. assertTrue('null is alpha', goog.string.isAlpha(null));
  120. assertTrue('undefined is alpha', goog.string.isAlpha(undefined));
  121. assertFalse('"aa!" is not alpha', goog.string.isAlpha('aa!s'));
  122. assertFalse('"!" is not alpha', goog.string.isAlpha('!'));
  123. assertFalse('"0" is not alpha', goog.string.isAlpha('0'));
  124. assertFalse('"5" is not alpha', goog.string.isAlpha('5'));
  125. }
  126. //=== tests for goog.string.isNumeric ===
  127. function testIsNumeric() {
  128. assertTrue('"8" is a numeric string', goog.string.isNumeric('8'));
  129. assertTrue('"5" is a numeric string', goog.string.isNumeric('5'));
  130. assertTrue('"34" is a numeric string', goog.string.isNumeric('34'));
  131. assertTrue('34 is a number', goog.string.isNumeric(34));
  132. assertFalse('"3.14" has a period', goog.string.isNumeric('3.14'));
  133. assertFalse('"A" is a letter', goog.string.isNumeric('A'));
  134. assertFalse('"!" is punctuation', goog.string.isNumeric('!'));
  135. assertFalse('null is not numeric', goog.string.isNumeric(null));
  136. assertFalse('undefined is not numeric', goog.string.isNumeric(undefined));
  137. }
  138. //=== tests for tests for goog.string.isAlphaNumeric ===
  139. function testIsAlphaNumeric() {
  140. assertTrue(
  141. '"ABCabc" should be alphanumeric', goog.string.isAlphaNumeric('ABCabc'));
  142. assertTrue('"123" should be alphanumeric', goog.string.isAlphaNumeric('123'));
  143. assertTrue(
  144. '"ABCabc123" should be alphanumeric',
  145. goog.string.isAlphaNumeric('ABCabc123'));
  146. assertTrue('null is alphanumeric', goog.string.isAlphaNumeric(null));
  147. assertTrue(
  148. 'undefined is alphanumeric', goog.string.isAlphaNumeric(undefined));
  149. assertFalse(
  150. '"123!" should not be alphanumeric', goog.string.isAlphaNumeric('123!'));
  151. assertFalse(
  152. '" " should not be alphanumeric', goog.string.isAlphaNumeric(' '));
  153. }
  154. //== tests for goog.string.isBreakingWhitespace ===
  155. function testIsBreakingWhitespace() {
  156. assertTrue('" " is breaking', goog.string.isBreakingWhitespace(' '));
  157. assertTrue('"\\n" is breaking', goog.string.isBreakingWhitespace('\n'));
  158. assertTrue('"\\t" is breaking', goog.string.isBreakingWhitespace('\t'));
  159. assertTrue('"\\r" is breaking', goog.string.isBreakingWhitespace('\r'));
  160. assertTrue(
  161. '"\\r\\n\\t " is breaking', goog.string.isBreakingWhitespace('\r\n\t '));
  162. assertFalse('nbsp is non-breaking', goog.string.isBreakingWhitespace('\xa0'));
  163. assertFalse('"a" is non-breaking', goog.string.isBreakingWhitespace('a'));
  164. assertFalse(
  165. '"a\\r" is non-breaking', goog.string.isBreakingWhitespace('a\r'));
  166. }
  167. //=== tests for goog.string.isSpace ===
  168. function testIsSpace() {
  169. assertTrue('" " is a space', goog.string.isSpace(' '));
  170. assertFalse('"\\n" is not a space', goog.string.isSpace('\n'));
  171. assertFalse('"\\t" is not a space', goog.string.isSpace('\t'));
  172. assertFalse(
  173. '" " is not a space, it\'s two spaces', goog.string.isSpace(' '));
  174. assertFalse('"a" is not a space', goog.string.isSpace('a'));
  175. assertFalse('"3" is not a space', goog.string.isSpace('3'));
  176. assertFalse('"#" is not a space', goog.string.isSpace('#'));
  177. assertFalse('null is not a space', goog.string.isSpace(null));
  178. assertFalse('nbsp is not a space', goog.string.isSpace('\xa0'));
  179. }
  180. // === tests for goog.string.stripNewlines ===
  181. function testStripNewLines() {
  182. assertEquals(
  183. 'Should replace new lines with spaces',
  184. goog.string.stripNewlines('some\nlines\rthat\r\nare\n\nsplit'),
  185. 'some lines that are split');
  186. }
  187. // === tests for goog.string.canonicalizeNewlines ===
  188. function testCanonicalizeNewlines() {
  189. assertEquals(
  190. 'Should replace all types of new line with \\n',
  191. goog.string.canonicalizeNewlines('some\nlines\rthat\r\nare\n\nsplit'),
  192. 'some\nlines\nthat\nare\n\nsplit');
  193. }
  194. // === tests for goog.string.normalizeWhitespace ===
  195. function testNormalizeWhitespace() {
  196. assertEquals(
  197. 'All whitespace chars should be replaced with a normal space',
  198. goog.string.normalizeWhitespace('\xa0 \n\t \xa0 \n\t'), ' ');
  199. }
  200. // === tests for goog.string.normalizeSpaces ===
  201. function testNormalizeSpaces() {
  202. assertEquals(
  203. 'All whitespace chars should be replaced with a normal space',
  204. goog.string.normalizeSpaces('\xa0 \t \xa0 \t'), ' ');
  205. }
  206. function testCollapseBreakingSpaces() {
  207. assertEquals(
  208. 'breaking spaces are collapsed', 'a b',
  209. goog.string.collapseBreakingSpaces(' \t\r\n a \t\r\n b \t\r\n '));
  210. assertEquals(
  211. 'non-breaking spaces are kept', 'a \u00a0\u2000 b',
  212. goog.string.collapseBreakingSpaces('a \u00a0\u2000 b'));
  213. }
  214. /// === tests for goog.string.trim ===
  215. function testTrim() {
  216. assertEquals(
  217. 'Should be the same', goog.string.trim('nothing 2 trim'),
  218. 'nothing 2 trim');
  219. assertEquals(
  220. 'Remove spaces', goog.string.trim(' hello goodbye '),
  221. 'hello goodbye');
  222. assertEquals(
  223. 'Trim other stuff', goog.string.trim('\n\r\xa0 hi \r\n\xa0'), 'hi');
  224. }
  225. /// === tests for goog.string.trimLeft ===
  226. function testTrimLeft() {
  227. var f = goog.string.trimLeft;
  228. assertEquals('Should be the same', f('nothing to trim'), 'nothing to trim');
  229. assertEquals('Remove spaces', f(' hello goodbye '), 'hello goodbye ');
  230. assertEquals('Trim other stuff', f('\xa0\n\r hi \r\n\xa0'), 'hi \r\n\xa0');
  231. }
  232. /// === tests for goog.string.trimRight ===
  233. function testTrimRight() {
  234. var f = goog.string.trimRight;
  235. assertEquals('Should be the same', f('nothing to trim'), 'nothing to trim');
  236. assertEquals('Remove spaces', f(' hello goodbye '), ' hello goodbye');
  237. assertEquals('Trim other stuff', f('\n\r\xa0 hi \r\n\xa0'), '\n\r\xa0 hi');
  238. }
  239. // === tests for goog.string.startsWith ===
  240. function testStartsWith() {
  241. assertTrue('Should start with \'\'', goog.string.startsWith('abcd', ''));
  242. assertTrue('Should start with \'ab\'', goog.string.startsWith('abcd', 'ab'));
  243. assertTrue(
  244. 'Should start with \'abcd\'', goog.string.startsWith('abcd', 'abcd'));
  245. assertFalse(
  246. 'Should not start with \'bcd\'', goog.string.startsWith('abcd', 'bcd'));
  247. }
  248. function testEndsWith() {
  249. assertTrue('Should end with \'\'', goog.string.endsWith('abcd', ''));
  250. assertTrue('Should end with \'ab\'', goog.string.endsWith('abcd', 'cd'));
  251. assertTrue('Should end with \'abcd\'', goog.string.endsWith('abcd', 'abcd'));
  252. assertFalse('Should not end \'abc\'', goog.string.endsWith('abcd', 'abc'));
  253. assertFalse(
  254. 'Should not end \'abcde\'', goog.string.endsWith('abcd', 'abcde'));
  255. }
  256. // === tests for goog.string.caseInsensitiveStartsWith ===
  257. function testCaseInsensitiveStartsWith() {
  258. assertTrue(
  259. 'Should start with \'\'',
  260. goog.string.caseInsensitiveStartsWith('abcd', ''));
  261. assertTrue(
  262. 'Should start with \'ab\'',
  263. goog.string.caseInsensitiveStartsWith('abcd', 'Ab'));
  264. assertTrue(
  265. 'Should start with \'abcd\'',
  266. goog.string.caseInsensitiveStartsWith('AbCd', 'abCd'));
  267. assertFalse(
  268. 'Should not start with \'bcd\'',
  269. goog.string.caseInsensitiveStartsWith('ABCD', 'bcd'));
  270. }
  271. // === tests for goog.string.caseInsensitiveEndsWith ===
  272. function testCaseInsensitiveEndsWith() {
  273. assertTrue(
  274. 'Should end with \'\'', goog.string.caseInsensitiveEndsWith('abcd', ''));
  275. assertTrue(
  276. 'Should end with \'cd\'',
  277. goog.string.caseInsensitiveEndsWith('abCD', 'cd'));
  278. assertTrue(
  279. 'Should end with \'abcd\'',
  280. goog.string.caseInsensitiveEndsWith('abcd', 'abCd'));
  281. assertFalse(
  282. 'Should not end \'abc\'',
  283. goog.string.caseInsensitiveEndsWith('aBCd', 'ABc'));
  284. assertFalse(
  285. 'Should not end \'abcde\'',
  286. goog.string.caseInsensitiveEndsWith('ABCD', 'abcde'));
  287. }
  288. // === tests for goog.string.caseInsensitiveEquals ===
  289. function testCaseInsensitiveEquals() {
  290. function assertCaseInsensitiveEquals(str1, str2) {
  291. assertTrue(goog.string.caseInsensitiveEquals(str1, str2));
  292. }
  293. function assertCaseInsensitiveNotEquals(str1, str2) {
  294. assertFalse(goog.string.caseInsensitiveEquals(str1, str2));
  295. }
  296. assertCaseInsensitiveEquals('abc', 'abc');
  297. assertCaseInsensitiveEquals('abc', 'abC');
  298. assertCaseInsensitiveEquals('d,e,F,G', 'd,e,F,G');
  299. assertCaseInsensitiveEquals('ABCD EFGH 1234', 'abcd efgh 1234');
  300. assertCaseInsensitiveEquals('FooBarBaz', 'fOObARbAZ');
  301. assertCaseInsensitiveNotEquals('ABCD EFGH', 'abcd efg');
  302. assertCaseInsensitiveNotEquals('ABC DEFGH', 'ABCD EFGH');
  303. assertCaseInsensitiveNotEquals('FooBarBaz', 'fOObARbAZ ');
  304. }
  305. // === tests for goog.string.subs ===
  306. function testSubs() {
  307. assertEquals(
  308. 'Should be the same', 'nothing to subs',
  309. goog.string.subs('nothing to subs'));
  310. assertEquals('Should be the same', '1', goog.string.subs('%s', '1'));
  311. assertEquals(
  312. 'Should be the same', '12true', goog.string.subs('%s%s%s', '1', 2, true));
  313. function f() { fail('This should not be called'); }
  314. f.toString = function() { return 'f'; };
  315. assertEquals('Should not call function', 'f', goog.string.subs('%s', f));
  316. // If the string that is to be substituted in contains $& then it will be
  317. // usually be replaced with %s, we need to check goog.string.subs, handles
  318. // this case.
  319. assertEquals(
  320. '$& should not be substituted with %s', 'Foo Bar $&',
  321. goog.string.subs('Foo %s', 'Bar $&'));
  322. assertEquals(
  323. '$$ should not be substituted', '_$$_', goog.string.subs('%s', '_$$_'));
  324. assertEquals(
  325. '$` should not be substituted', '_$`_', goog.string.subs('%s', '_$`_'));
  326. assertEquals(
  327. '$\' should not be substituted', '_$\'_',
  328. goog.string.subs('%s', '_$\'_'));
  329. for (var i = 0; i < 99; i += 9) {
  330. assertEquals(
  331. '$' + i + ' should not be substituted', '_$' + i + '_',
  332. goog.string.subs('%s', '_$' + i + '_'));
  333. }
  334. assertEquals(
  335. 'Only the first three "%s" strings should be replaced.',
  336. 'test foo test bar test baz test %s test %s test',
  337. goog.string.subs(
  338. 'test %s test %s test %s test %s test %s test', 'foo', 'bar', 'baz'));
  339. }
  340. /**
  341. * Verifies that if too many arguments are given, they are ignored.
  342. * Logic test for bug documented here: http://go/eusxz
  343. */
  344. function testSubsTooManyArguments() {
  345. assertEquals('one', goog.string.subs('one', 'two', 'three'));
  346. assertEquals('onetwo', goog.string.subs('one%s', 'two', 'three'));
  347. }
  348. // === tests for goog.string.caseInsensitiveCompare ===
  349. function testCaseInsensitiveCompare() {
  350. var f = goog.string.caseInsensitiveCompare;
  351. assert('"ABC" should be less than "def"', f('ABC', 'def') == -1);
  352. assert('"abc" should be less than "DEF"', f('abc', 'DEF') == -1);
  353. assert('"XYZ" should equal "xyz"', f('XYZ', 'xyz') == 0);
  354. assert('"XYZ" should be greater than "UVW"', f('xyz', 'UVW') == 1);
  355. assert('"XYZ" should be greater than "uvw"', f('XYZ', 'uvw') == 1);
  356. }
  357. /**
  358. * Test cases for goog.string.floatAwareCompare and goog.string.intAwareCompare.
  359. * Each comparison in this list is tested to assure that terms[0] < terms[1],
  360. * terms[1] > terms[0], and identity tests terms[0] == terms[0] and
  361. * terms[1] == terms[1].
  362. * @const {!Array<!Array<string>>}
  363. */
  364. var NUMERIC_COMPARISON_TEST_CASES = [
  365. ['', '0'], ['2', '10'], ['05', '9'], ['sub', 'substring'],
  366. ['photo 7', 'Photo 8'], // Case insensitive for most sorts.
  367. ['Mango', 'mango'], // Case sensitive if strings are otherwise identical.
  368. ['album 2 photo 20', 'album 10 photo 20'],
  369. ['album 7 photo 20', 'album 7 photo 100']
  370. ];
  371. function testFloatAwareCompare() {
  372. var comparisons = NUMERIC_COMPARISON_TEST_CASES.concat([['3.14', '3.2']]);
  373. for (var i = 0; i < comparisons.length; i++) {
  374. var terms = comparisons[i];
  375. assert(
  376. terms[0] + ' should be less than ' + terms[1],
  377. goog.string.floatAwareCompare(terms[0], terms[1]) < 0);
  378. assert(
  379. terms[1] + ' should be greater than ' + terms[0],
  380. goog.string.floatAwareCompare(terms[1], terms[0]) > 0);
  381. assert(
  382. terms[0] + ' should be equal to ' + terms[0],
  383. goog.string.floatAwareCompare(terms[0], terms[0]) == 0);
  384. assert(
  385. terms[1] + ' should be equal to ' + terms[1],
  386. goog.string.floatAwareCompare(terms[1], terms[1]) == 0);
  387. }
  388. }
  389. function testIntAwareCompare() {
  390. var comparisons = NUMERIC_COMPARISON_TEST_CASES.concat([['3.2', '3.14']]);
  391. for (var i = 0; i < comparisons.length; i++) {
  392. var terms = comparisons[i];
  393. assert(
  394. terms[0] + ' should be less than ' + terms[1],
  395. goog.string.intAwareCompare(terms[0], terms[1]) < 0);
  396. assert(
  397. terms[1] + ' should be greater than ' + terms[0],
  398. goog.string.intAwareCompare(terms[1], terms[0]) > 0);
  399. assert(
  400. terms[0] + ' should be equal to ' + terms[0],
  401. goog.string.intAwareCompare(terms[0], terms[0]) == 0);
  402. assert(
  403. terms[1] + ' should be equal to ' + terms[1],
  404. goog.string.intAwareCompare(terms[1], terms[1]) == 0);
  405. }
  406. }
  407. // === tests for goog.string.urlEncode && .urlDecode ===
  408. // NOTE: When test was written it was simply an alias for the built in
  409. // 'encodeURICompoent', therefore this test is simply used to make sure that in
  410. // the future it doesn't get broken.
  411. function testUrlEncodeAndDecode() {
  412. var input = '<p>"hello there," she said, "what is going on here?</p>';
  413. var output = '%3Cp%3E%22hello%20there%2C%22%20she%20said%2C%20%22what%20is' +
  414. '%20going%20on%20here%3F%3C%2Fp%3E';
  415. assertEquals(
  416. 'urlEncode vs encodeURIComponent', encodeURIComponent(input),
  417. goog.string.urlEncode(input));
  418. assertEquals('urlEncode vs model', goog.string.urlEncode(input), output);
  419. assertEquals('urlDecode vs model', goog.string.urlDecode(output), input);
  420. assertEquals(
  421. 'urlDecode vs urlEncode',
  422. goog.string.urlDecode(goog.string.urlEncode(input)), input);
  423. assertEquals(
  424. 'urlDecode with +s instead of %20s',
  425. goog.string.urlDecode(output.replace(/%20/g, '+')), input);
  426. }
  427. // === tests for goog.string.newLineToBr ===
  428. function testNewLineToBr() {
  429. var str = 'some\nlines\rthat\r\nare\n\nsplit';
  430. var html = 'some<br>lines<br>that<br>are<br><br>split';
  431. var xhtml = 'some<br />lines<br />that<br />are<br /><br />split';
  432. assertEquals('Should be html', goog.string.newLineToBr(str), html);
  433. assertEquals('Should be html', goog.string.newLineToBr(str, false), html);
  434. assertEquals('Should be xhtml', goog.string.newLineToBr(str, true), xhtml);
  435. }
  436. // === tests for goog.string.htmlEscape and .unescapeEntities ===
  437. function testHtmlEscapeAndUnescapeEntities() {
  438. var text = '\'"x1 < x2 && y2 > y1"\'';
  439. var html = '&#39;&quot;x1 &lt; x2 &amp;&amp; y2 &gt; y1&quot;&#39;';
  440. assertEquals('Testing htmlEscape', html, goog.string.htmlEscape(text));
  441. assertEquals('Testing htmlEscape', html, goog.string.htmlEscape(text, false));
  442. assertEquals('Testing htmlEscape', html, goog.string.htmlEscape(text, true));
  443. assertEquals(
  444. 'Testing unescapeEntities', text, goog.string.unescapeEntities(html));
  445. assertEquals(
  446. 'escape -> unescape', text,
  447. goog.string.unescapeEntities(goog.string.htmlEscape(text)));
  448. assertEquals(
  449. 'unescape -> escape', html,
  450. goog.string.htmlEscape(goog.string.unescapeEntities(html)));
  451. }
  452. function testHtmlUnescapeEntitiesWithDocument() {
  453. var documentMock = {
  454. createElement: mockControl.createFunctionMock('createElement')
  455. };
  456. var divMock = goog.dom.createElement(goog.dom.TagName.DIV);
  457. documentMock.createElement('div').$returns(divMock);
  458. mockControl.$replayAll();
  459. var html = '&lt;a&b&gt;';
  460. var text = '<a&b>';
  461. assertEquals(
  462. 'wrong unescaped value', text,
  463. goog.string.unescapeEntitiesWithDocument(html, documentMock));
  464. assertNotEquals(
  465. 'divMock.innerHTML should have been used', '', divMock.innerHTML);
  466. mockControl.$verifyAll();
  467. }
  468. function testHtmlEscapeAndUnescapeEntitiesUsingDom() {
  469. var text = '"x1 < x2 && y2 > y1"';
  470. var html = '&quot;x1 &lt; x2 &amp;&amp; y2 &gt; y1&quot;';
  471. assertEquals(
  472. 'Testing unescapeEntities', goog.string.unescapeEntitiesUsingDom_(html),
  473. text);
  474. assertEquals(
  475. 'escape -> unescape',
  476. goog.string.unescapeEntitiesUsingDom_(goog.string.htmlEscape(text)),
  477. text);
  478. assertEquals(
  479. 'unescape -> escape',
  480. goog.string.htmlEscape(goog.string.unescapeEntitiesUsingDom_(html)),
  481. html);
  482. }
  483. function testHtmlUnescapeEntitiesUsingDom_withAmpersands() {
  484. var html = '&lt;a&b&gt;';
  485. var text = '<a&b>';
  486. assertEquals(
  487. 'wrong unescaped value', text,
  488. goog.string.unescapeEntitiesUsingDom_(html));
  489. }
  490. function testHtmlEscapeAndUnescapePureXmlEntities_() {
  491. var text = '"x1 < x2 && y2 > y1"';
  492. var html = '&quot;x1 &lt; x2 &amp;&amp; y2 &gt; y1&quot;';
  493. assertEquals(
  494. 'Testing unescapePureXmlEntities_',
  495. goog.string.unescapePureXmlEntities_(html), text);
  496. assertEquals(
  497. 'escape -> unescape',
  498. goog.string.unescapePureXmlEntities_(goog.string.htmlEscape(text)), text);
  499. assertEquals(
  500. 'unescape -> escape',
  501. goog.string.htmlEscape(goog.string.unescapePureXmlEntities_(html)), html);
  502. }
  503. function testForceNonDomHtmlUnescaping() {
  504. stubs.set(goog.string, 'FORCE_NON_DOM_HTML_UNESCAPING', true);
  505. // Set document.createElement to empty object so that the call to
  506. // unescapeEntities will blow up if html unescaping is carried out with DOM.
  507. // Notice that we can't directly set document to empty object since IE8 won't
  508. // let us do so.
  509. stubs.set(goog.global.document, 'createElement', {});
  510. goog.string.unescapeEntities('&quot;x1 &lt; x2 &amp;&amp; y2 &gt; y1&quot;');
  511. }
  512. function testHtmlEscapeDetectDoubleEscaping() {
  513. stubs.set(goog.string, 'DETECT_DOUBLE_ESCAPING', true);
  514. assertEquals('&#101; &lt; pi', goog.string.htmlEscape('e < pi'));
  515. assertEquals('&#101; &lt; pi', goog.string.htmlEscape('e < pi', true));
  516. }
  517. function testHtmlEscapeNullByte() {
  518. assertEquals('&#0;', goog.string.htmlEscape('\x00'));
  519. assertEquals('&#0;', goog.string.htmlEscape('\x00', true));
  520. assertEquals('\\x00', goog.string.htmlEscape('\\x00'));
  521. assertEquals('\\x00', goog.string.htmlEscape('\\x00', true));
  522. }
  523. var globalXssVar = 0;
  524. function testXssUnescapeEntities() {
  525. // This tests that we don't have any XSS exploits in unescapeEntities
  526. var test = '&amp;<script defer>globalXssVar=1;</' +
  527. 'script>';
  528. var expected = '&<script defer>globalXssVar=1;</' +
  529. 'script>';
  530. assertEquals(
  531. 'Testing unescapeEntities', expected, goog.string.unescapeEntities(test));
  532. assertEquals('unescapeEntities is vulnarable to XSS', 0, globalXssVar);
  533. test = '&amp;<script>globalXssVar=1;</' +
  534. 'script>';
  535. expected = '&<script>globalXssVar=1;</' +
  536. 'script>';
  537. assertEquals(
  538. 'Testing unescapeEntities', expected, goog.string.unescapeEntities(test));
  539. assertEquals('unescapeEntities is vulnarable to XSS', 0, globalXssVar);
  540. }
  541. function testXssUnescapeEntitiesUsingDom() {
  542. // This tests that we don't have any XSS exploits in unescapeEntitiesUsingDom
  543. var test = '&amp;<script defer>globalXssVar=1;</' +
  544. 'script>';
  545. var expected = '&<script defer>globalXssVar=1;</' +
  546. 'script>';
  547. assertEquals(
  548. 'Testing unescapeEntitiesUsingDom_', expected,
  549. goog.string.unescapeEntitiesUsingDom_(test));
  550. assertEquals(
  551. 'unescapeEntitiesUsingDom_ is vulnerable to XSS', 0, globalXssVar);
  552. test = '&amp;<script>globalXssVar=1;</' +
  553. 'script>';
  554. expected = '&<script>globalXssVar=1;</' +
  555. 'script>';
  556. assertEquals(
  557. 'Testing unescapeEntitiesUsingDom_', expected,
  558. goog.string.unescapeEntitiesUsingDom_(test));
  559. assertEquals(
  560. 'unescapeEntitiesUsingDom_ is vulnerable to XSS', 0, globalXssVar);
  561. }
  562. function testXssUnescapePureXmlEntities() {
  563. // This tests that we don't have any XSS exploits in unescapePureXmlEntities
  564. var test = '&amp;<script defer>globalXssVar=1;</' +
  565. 'script>';
  566. var expected = '&<script defer>globalXssVar=1;</' +
  567. 'script>';
  568. assertEquals(
  569. 'Testing unescapePureXmlEntities_', expected,
  570. goog.string.unescapePureXmlEntities_(test));
  571. assertEquals(
  572. 'unescapePureXmlEntities_ is vulnarable to XSS', 0, globalXssVar);
  573. test = '&amp;<script>globalXssVar=1;</' +
  574. 'script>';
  575. expected = '&<script>globalXssVar=1;</' +
  576. 'script>';
  577. assertEquals(
  578. 'Testing unescapePureXmlEntities_', expected,
  579. goog.string.unescapePureXmlEntities_(test));
  580. assertEquals(
  581. 'unescapePureXmlEntities_ is vulnarable to XSS', 0, globalXssVar);
  582. }
  583. function testUnescapeEntitiesPreservesWhitespace() {
  584. // This tests that whitespace is preserved (primarily for IE)
  585. // Also make sure leading and trailing whitespace are preserved.
  586. var test = '\nTesting\n\twhitespace\n preservation\n';
  587. var expected = test;
  588. assertEquals(
  589. 'Testing unescapeEntities', expected, goog.string.unescapeEntities(test));
  590. // Now with entities
  591. test += ' &amp;&nbsp;\n';
  592. expected += ' &\u00A0\n';
  593. assertEquals(
  594. 'Testing unescapeEntities', expected, goog.string.unescapeEntities(test));
  595. }
  596. // === tests for goog.string.whitespaceEscape ===
  597. function testWhitespaceEscape() {
  598. assertEquals(
  599. 'Should be the same',
  600. goog.string.whitespaceEscape('one two three four five '),
  601. 'one two &#160;three &#160; four &#160; &#160;five &#160; &#160; ');
  602. }
  603. // === tests for goog.string.preserveSpaces ===
  604. function testPreserveSpaces() {
  605. var nbsp = goog.string.Unicode.NBSP;
  606. assertEquals('', goog.string.preserveSpaces(''));
  607. assertEquals(nbsp + 'a', goog.string.preserveSpaces(' a'));
  608. assertEquals(nbsp + ' a', goog.string.preserveSpaces(' a'));
  609. assertEquals(nbsp + ' ' + nbsp + 'a', goog.string.preserveSpaces(' a'));
  610. assertEquals('a ' + nbsp + 'b', goog.string.preserveSpaces('a b'));
  611. assertEquals('a\n' + nbsp + 'b', goog.string.preserveSpaces('a\n b'));
  612. // We don't care about trailing spaces.
  613. assertEquals('a ', goog.string.preserveSpaces('a '));
  614. assertEquals('a \n' + nbsp + 'b', goog.string.preserveSpaces('a \n b'));
  615. }
  616. // === tests for goog.string.stripQuotes ===
  617. function testStripQuotes() {
  618. assertEquals(
  619. 'Quotes should be stripped', goog.string.stripQuotes('"hello"', '"'),
  620. 'hello');
  621. assertEquals(
  622. 'Quotes should be stripped', goog.string.stripQuotes('\'hello\'', '\''),
  623. 'hello');
  624. assertEquals(
  625. 'Quotes should not be stripped', goog.string.stripQuotes('-"hello"', '"'),
  626. '-"hello"');
  627. }
  628. function testStripQuotesMultiple() {
  629. assertEquals(
  630. 'Quotes should be stripped', goog.string.stripQuotes('"hello"', '"\''),
  631. 'hello');
  632. assertEquals(
  633. 'Quotes should be stripped', goog.string.stripQuotes('\'hello\'', '"\''),
  634. 'hello');
  635. assertEquals(
  636. 'Quotes should be stripped', goog.string.stripQuotes('\'hello\'', ''),
  637. '\'hello\'');
  638. }
  639. function testStripQuotesMultiple2() {
  640. // Makes sure we do not strip twice
  641. assertEquals(
  642. 'Quotes should be stripped',
  643. goog.string.stripQuotes('"\'hello\'"', '"\''), '\'hello\'');
  644. assertEquals(
  645. 'Quotes should be stripped',
  646. goog.string.stripQuotes('"\'hello\'"', '\'"'), '\'hello\'');
  647. }
  648. // === tests for goog.string.truncate ===
  649. function testTruncate() {
  650. var str = 'abcdefghijklmnopqrstuvwxyz';
  651. assertEquals('Should be equal', goog.string.truncate(str, 8), 'abcde...');
  652. assertEquals('Should be equal', goog.string.truncate(str, 11), 'abcdefgh...');
  653. var html = 'true &amp;&amp; false == false';
  654. assertEquals(
  655. 'Should clip html char', goog.string.truncate(html, 11), 'true &am...');
  656. assertEquals(
  657. 'Should not clip html char', goog.string.truncate(html, 12, true),
  658. 'true &amp;&amp; f...');
  659. }
  660. // === tests for goog.string.truncateMiddle ===
  661. function testTruncateMiddle() {
  662. var str = 'abcdefghijklmnopqrstuvwxyz';
  663. assertEquals('abc...xyz', goog.string.truncateMiddle(str, 6));
  664. assertEquals('abc...yz', goog.string.truncateMiddle(str, 5));
  665. assertEquals(str, goog.string.truncateMiddle(str, str.length));
  666. var html = 'true &amp;&amp; false == false';
  667. assertEquals(
  668. 'Should clip html char', 'true &a...= false',
  669. goog.string.truncateMiddle(html, 14));
  670. assertEquals(
  671. 'Should not clip html char', 'true &amp;&amp;...= false',
  672. goog.string.truncateMiddle(html, 14, true));
  673. assertEquals('ab...xyz', goog.string.truncateMiddle(str, 5, null, 3));
  674. assertEquals('abcdefg...xyz', goog.string.truncateMiddle(str, 10, null, 3));
  675. assertEquals('abcdef...wxyz', goog.string.truncateMiddle(str, 10, null, 4));
  676. assertEquals('...yz', goog.string.truncateMiddle(str, 2, null, 3));
  677. assertEquals(str, goog.string.truncateMiddle(str, 50, null, 3));
  678. assertEquals(
  679. 'Should clip html char', 'true &amp;&...lse',
  680. goog.string.truncateMiddle(html, 14, null, 3));
  681. assertEquals(
  682. 'Should not clip html char', 'true &amp;&amp; fal...lse',
  683. goog.string.truncateMiddle(html, 14, true, 3));
  684. }
  685. // === goog.string.quote ===
  686. function testQuote() {
  687. var str = allChars();
  688. assertEquals(str, eval(goog.string.quote(str)));
  689. // empty string
  690. assertEquals('', eval(goog.string.quote('')));
  691. // unicode
  692. str = allChars(0, 10000);
  693. assertEquals(str, eval(goog.string.quote(str)));
  694. }
  695. function testQuoteSpecialChars() {
  696. assertEquals('"\\""', goog.string.quote('"'));
  697. assertEquals('"\'"', goog.string.quote("'"));
  698. assertEquals('"\\\\"', goog.string.quote('\\'));
  699. assertEquals('"\x3c"', goog.string.quote('<'));
  700. var zeroQuoted = goog.string.quote('\0');
  701. assertTrue(
  702. 'goog.string.quote mangles the 0 char: ',
  703. '"\\0"' == zeroQuoted || '"\\x00"' == zeroQuoted);
  704. }
  705. function testCrossBrowserQuote() {
  706. // The vertical space char has weird semantics on jscript, so we don't test
  707. // that one.
  708. var vertChar = '\x0B'.charCodeAt(0);
  709. // The zero char has two alternate encodings (\0 and \x00) both are ok,
  710. // and tested above.
  711. var zeroChar = 0;
  712. var str = allChars(zeroChar + 1, vertChar) + allChars(vertChar + 1, 10000);
  713. var nativeQuote = goog.string.quote(str);
  714. stubs.set(String.prototype, 'quote', null);
  715. assertNull(''.quote);
  716. assertEquals(nativeQuote, goog.string.quote(str));
  717. }
  718. function allChars(opt_start, opt_end) {
  719. opt_start = opt_start || 0;
  720. opt_end = opt_end || 256;
  721. var rv = '';
  722. for (var i = opt_start; i < opt_end; i++) {
  723. rv += String.fromCharCode(i);
  724. }
  725. return rv;
  726. }
  727. function testEscapeString() {
  728. var expected = allChars(0, 10000);
  729. try {
  730. var actual = eval('"' + goog.string.escapeString(expected) + '"');
  731. } catch (e) {
  732. fail('Quote failed: err ' + e.message);
  733. }
  734. assertEquals(expected, actual);
  735. }
  736. function testCountOf() {
  737. assertEquals(goog.string.countOf('REDSOXROX', undefined), 0);
  738. assertEquals(goog.string.countOf('REDSOXROX', null), 0);
  739. assertEquals(goog.string.countOf('REDSOXROX', ''), 0);
  740. assertEquals(goog.string.countOf('', undefined), 0);
  741. assertEquals(goog.string.countOf('', null), 0);
  742. assertEquals(goog.string.countOf('', ''), 0);
  743. assertEquals(goog.string.countOf('', 'REDSOXROX'), 0);
  744. assertEquals(goog.string.countOf(undefined, 'R'), 0);
  745. assertEquals(goog.string.countOf(null, 'R'), 0);
  746. assertEquals(goog.string.countOf(undefined, undefined), 0);
  747. assertEquals(goog.string.countOf(null, null), 0);
  748. assertEquals(goog.string.countOf('REDSOXROX', 'R'), 2);
  749. assertEquals(goog.string.countOf('REDSOXROX', 'E'), 1);
  750. assertEquals(goog.string.countOf('REDSOXROX', 'X'), 2);
  751. assertEquals(goog.string.countOf('REDSOXROX', 'RED'), 1);
  752. assertEquals(goog.string.countOf('REDSOXROX', 'ROX'), 1);
  753. assertEquals(goog.string.countOf('REDSOXROX', 'OX'), 2);
  754. assertEquals(goog.string.countOf('REDSOXROX', 'Z'), 0);
  755. assertEquals(goog.string.countOf('REDSOXROX', 'REDSOXROX'), 1);
  756. assertEquals(goog.string.countOf('REDSOXROX', 'YANKEES'), 0);
  757. assertEquals(goog.string.countOf('REDSOXROX', 'EVIL_EMPIRE'), 0);
  758. assertEquals(goog.string.countOf('RRRRRRRRR', 'R'), 9);
  759. assertEquals(goog.string.countOf('RRRRRRRRR', 'RR'), 4);
  760. assertEquals(goog.string.countOf('RRRRRRRRR', 'RRR'), 3);
  761. assertEquals(goog.string.countOf('RRRRRRRRR', 'RRRR'), 2);
  762. assertEquals(goog.string.countOf('RRRRRRRRR', 'RRRRR'), 1);
  763. assertEquals(goog.string.countOf('RRRRRRRRR', 'RRRRRR'), 1);
  764. }
  765. function testRemoveAt() {
  766. var str = 'barfoobarbazbar';
  767. str = goog.string.removeAt(str, 0, 3);
  768. assertEquals('Remove first bar', 'foobarbazbar', str);
  769. str = goog.string.removeAt(str, 3, 3);
  770. assertEquals('Remove middle bar', 'foobazbar', str);
  771. str = goog.string.removeAt(str, 6, 3);
  772. assertEquals('Remove last bar', 'foobaz', str);
  773. assertEquals(
  774. 'Invalid negative index', 'foobaz', goog.string.removeAt(str, -1, 0));
  775. assertEquals(
  776. 'Invalid overflow index', 'foobaz', goog.string.removeAt(str, 9, 0));
  777. assertEquals(
  778. 'Invalid negative stringLength', 'foobaz',
  779. goog.string.removeAt(str, 0, -1));
  780. assertEquals(
  781. 'Invalid overflow stringLength', '', goog.string.removeAt(str, 0, 9));
  782. assertEquals(
  783. 'Invalid overflow index and stringLength', 'foobaz',
  784. goog.string.removeAt(str, 9, 9));
  785. assertEquals(
  786. 'Invalid zero stringLength', 'foobaz', goog.string.removeAt(str, 0, 0));
  787. }
  788. function testRemove() {
  789. var str = 'barfoobarbazbar';
  790. str = goog.string.remove(str, 'bar');
  791. assertEquals('Remove first bar', 'foobarbazbar', str);
  792. str = goog.string.remove(str, 'bar');
  793. assertEquals('Remove middle bar', 'foobazbar', str);
  794. str = goog.string.remove(str, 'bar');
  795. assertEquals('Remove last bar', 'foobaz', str);
  796. str = goog.string.remove(str, 'bar');
  797. assertEquals('Original string', 'foobaz', str);
  798. }
  799. function testRemoveAll() {
  800. var str = 'foobarbazbarfoobazfoo';
  801. str = goog.string.removeAll(str, 'foo');
  802. assertEquals('Remove all occurrences of foo', 'barbazbarbaz', str);
  803. str = goog.string.removeAll(str, 'foo');
  804. assertEquals('Original string', 'barbazbarbaz', str);
  805. }
  806. function testReplaceAll() {
  807. var str = 'foobarbazbarfoobazfoo';
  808. str = goog.string.replaceAll(str, 'foo', 'test');
  809. assertEquals(
  810. 'Replace all occurrences of foo with test', 'testbarbazbartestbaztest',
  811. str);
  812. var str2 = 'foobarbazbar^foo$baz^foo$';
  813. str2 = goog.string.replaceAll(str2, '^foo', '$&test');
  814. assertEquals(
  815. 'Replace all occurrences of ^foo with $&test',
  816. 'foobarbazbar$&test$baz$&test$', str2);
  817. }
  818. function testRegExpEscape() {
  819. var spec = '()[]{}+-?*.$^|,:#<!\\';
  820. var escapedSpec = '\\' + spec.split('').join('\\');
  821. assertEquals('special chars', escapedSpec, goog.string.regExpEscape(spec));
  822. assertEquals('backslash b', '\\x08', goog.string.regExpEscape('\b'));
  823. var s = allChars();
  824. var re = new RegExp('^' + goog.string.regExpEscape(s) + '$');
  825. assertTrue('All ASCII', re.test(s));
  826. s = '';
  827. re = new RegExp('^' + goog.string.regExpEscape(s) + '$');
  828. assertTrue('empty string', re.test(s));
  829. s = allChars(0, 10000);
  830. re = new RegExp('^' + goog.string.regExpEscape(s) + '$');
  831. assertTrue('Unicode', re.test(s));
  832. }
  833. function testPadNumber() {
  834. assertEquals('01.250', goog.string.padNumber(1.25, 2, 3));
  835. assertEquals('01.25', goog.string.padNumber(1.25, 2));
  836. assertEquals('01.3', goog.string.padNumber(1.25, 2, 1));
  837. assertEquals('1.25', goog.string.padNumber(1.25, 0));
  838. assertEquals('10', goog.string.padNumber(9.9, 2, 0));
  839. assertEquals('7', goog.string.padNumber(7, 0));
  840. assertEquals('7', goog.string.padNumber(7, 1));
  841. assertEquals('07', goog.string.padNumber(7, 2));
  842. }
  843. function testAsString() {
  844. assertEquals('', goog.string.makeSafe(null));
  845. assertEquals('', goog.string.makeSafe(undefined));
  846. assertEquals('', goog.string.makeSafe(''));
  847. assertEquals('abc', goog.string.makeSafe('abc'));
  848. assertEquals('123', goog.string.makeSafe(123));
  849. assertEquals('0', goog.string.makeSafe(0));
  850. assertEquals('true', goog.string.makeSafe(true));
  851. assertEquals('false', goog.string.makeSafe(false));
  852. var funky = function() {};
  853. funky.toString = function() { return 'funky-thing' };
  854. assertEquals('funky-thing', goog.string.makeSafe(funky));
  855. }
  856. function testStringRepeat() {
  857. assertEquals('', goog.string.repeat('*', 0));
  858. assertEquals('*', goog.string.repeat('*', 1));
  859. assertEquals(' ', goog.string.repeat(' ', 5));
  860. assertEquals('__________', goog.string.repeat('_', 10));
  861. assertEquals('aaa', goog.string.repeat('a', 3));
  862. assertEquals('foofoofoofoofoofoo', goog.string.repeat('foo', 6));
  863. }
  864. function testBuildString() {
  865. assertEquals('', goog.string.buildString());
  866. assertEquals('a', goog.string.buildString('a'));
  867. assertEquals('ab', goog.string.buildString('ab'));
  868. assertEquals('ab', goog.string.buildString('a', 'b'));
  869. assertEquals('abcd', goog.string.buildString('a', 'b', 'c', 'd'));
  870. assertEquals('0', goog.string.buildString(0));
  871. assertEquals('0123', goog.string.buildString(0, 1, 2, 3));
  872. assertEquals('ab01', goog.string.buildString('a', 'b', 0, 1));
  873. assertEquals('', goog.string.buildString(null, undefined));
  874. }
  875. function testCompareVersions() {
  876. var f = goog.string.compareVersions;
  877. assertTrue('numeric equality broken', f(1, 1) == 0);
  878. assertTrue('numeric less than broken', f(1.0, 1.1) < 0);
  879. assertTrue('numeric greater than broken', f(2.0, 1.1) > 0);
  880. assertTrue('exact equality broken', f('1.0', '1.0') == 0);
  881. assertTrue('mutlidot equality broken', f('1.0.0.0', '1.0') == 0);
  882. assertTrue('mutlidigit equality broken', f('1.000', '1.0') == 0);
  883. assertTrue('less than broken', f('1.0.2.1', '1.1') < 0);
  884. assertTrue('greater than broken', f('1.1', '1.0.2.1') > 0);
  885. assertTrue('substring less than broken', f('1', '1.1') < 0);
  886. assertTrue('substring greater than broken', f('2.2', '2') > 0);
  887. assertTrue('b greater than broken', f('1.1', '1.1b') > 0);
  888. assertTrue('b less than broken', f('1.1b', '1.1') < 0);
  889. assertTrue('b equality broken', f('1.1b', '1.1b') == 0);
  890. assertTrue('b > a broken', f('1.1b', '1.1a') > 0);
  891. assertTrue('a < b broken', f('1.1a', '1.1b') < 0);
  892. assertTrue('9.5 < 9.10 broken', f('9.5', '9.10') < 0);
  893. assertTrue('9.5 < 9.11 broken', f('9.5', '9.11') < 0);
  894. assertTrue('9.11 > 9.10 broken', f('9.11', '9.10') > 0);
  895. assertTrue('9.1 < 9.10 broken', f('9.1', '9.10') < 0);
  896. assertTrue('9.1.1 < 9.10 broken', f('9.1.1', '9.10') < 0);
  897. assertTrue('9.1.1 < 9.11 broken', f('9.1.1', '9.11') < 0);
  898. assertTrue('10a > 9b broken', f('1.10a', '1.9b') > 0);
  899. assertTrue('b < b2 broken', f('1.1b', '1.1b2') < 0);
  900. assertTrue('b10 > b9 broken', f('1.1b10', '1.1b9') > 0);
  901. assertTrue('7 > 6 broken with leading whitespace', f(' 7', '6') > 0);
  902. assertTrue('7 > 6 broken with trailing whitespace', f('7 ', '6') > 0);
  903. }
  904. function testIsUnicodeChar() {
  905. assertFalse('empty string broken', goog.string.isUnicodeChar(''));
  906. assertFalse(
  907. 'non-single char string broken', goog.string.isUnicodeChar('abc'));
  908. assertTrue('space broken', goog.string.isUnicodeChar(' '));
  909. assertTrue('single char broken', goog.string.isUnicodeChar('a'));
  910. assertTrue('upper case broken', goog.string.isUnicodeChar('A'));
  911. assertTrue('unicode char broken', goog.string.isUnicodeChar('\u0C07'));
  912. }
  913. function assertHashcodeEquals(expectedHashCode, str) {
  914. assertEquals(
  915. 'wrong hashCode for ' + str.substring(0, 32), expectedHashCode,
  916. goog.string.hashCode(str));
  917. }
  918. /**
  919. * Verify we get random-ish looking values for hash of Strings.
  920. */
  921. function testHashCode() {
  922. try {
  923. goog.string.hashCode(null);
  924. fail('should throw exception for null');
  925. } catch (ex) {
  926. // success
  927. }
  928. assertHashcodeEquals(0, '');
  929. assertHashcodeEquals(101574, 'foo');
  930. assertHashcodeEquals(1301670364, '\uAAAAfoo');
  931. assertHashcodeEquals(92567585, goog.string.repeat('a', 5));
  932. assertHashcodeEquals(2869595232, goog.string.repeat('a', 6));
  933. assertHashcodeEquals(3058106369, goog.string.repeat('a', 7));
  934. assertHashcodeEquals(312017024, goog.string.repeat('a', 8));
  935. assertHashcodeEquals(2929737728, goog.string.repeat('a', 1024));
  936. }
  937. function testUniqueString() {
  938. var TEST_COUNT = 20;
  939. var obj = {};
  940. for (var i = 0; i < TEST_COUNT; i++) {
  941. obj[goog.string.createUniqueString()] = true;
  942. }
  943. assertEquals(
  944. 'All strings should be unique.', TEST_COUNT, goog.object.getCount(obj));
  945. }
  946. function testToNumber() {
  947. // First, test the cases goog.string.toNumber() was primarily written for,
  948. // because JS built-ins are dumb.
  949. assertNaN(goog.string.toNumber('123a'));
  950. assertNaN(goog.string.toNumber('123.456.78'));
  951. assertNaN(goog.string.toNumber(''));
  952. assertNaN(goog.string.toNumber(' '));
  953. // Now, sanity-check.
  954. assertEquals(123, goog.string.toNumber(' 123 '));
  955. assertEquals(321.123, goog.string.toNumber('321.123'));
  956. assertEquals(1.00001, goog.string.toNumber('1.00001'));
  957. assertEquals(1, goog.string.toNumber('1.00000'));
  958. assertEquals(0.2, goog.string.toNumber('0.20'));
  959. assertEquals(0, goog.string.toNumber('0'));
  960. assertEquals(0, goog.string.toNumber('0.0'));
  961. assertEquals(-1, goog.string.toNumber('-1'));
  962. assertEquals(-0.3, goog.string.toNumber('-.3'));
  963. assertEquals(-12.345, goog.string.toNumber('-12.345'));
  964. assertEquals(100, goog.string.toNumber('1e2'));
  965. assertEquals(0.123, goog.string.toNumber('12.3e-2'));
  966. assertNaN(goog.string.toNumber('abc'));
  967. }
  968. function testGetRandomString() {
  969. stubs.set(goog, 'now', goog.functions.constant(1295726605874));
  970. stubs.set(Math, 'random', goog.functions.constant(0.6679361383522245));
  971. assertTrue(
  972. 'String must be alphanumeric',
  973. goog.string.isAlphaNumeric(goog.string.getRandomString()));
  974. }
  975. function testToCamelCase() {
  976. assertEquals('OneTwoThree', goog.string.toCamelCase('-one-two-three'));
  977. assertEquals('oneTwoThree', goog.string.toCamelCase('one-two-three'));
  978. assertEquals('oneTwo', goog.string.toCamelCase('one-two'));
  979. assertEquals('one', goog.string.toCamelCase('one'));
  980. assertEquals('oneTwo', goog.string.toCamelCase('oneTwo'));
  981. assertEquals(
  982. 'String value matching a native function name.', 'toString',
  983. goog.string.toCamelCase('toString'));
  984. }
  985. function testToSelectorCase() {
  986. assertEquals('-one-two-three', goog.string.toSelectorCase('OneTwoThree'));
  987. assertEquals('one-two-three', goog.string.toSelectorCase('oneTwoThree'));
  988. assertEquals('one-two', goog.string.toSelectorCase('oneTwo'));
  989. assertEquals('one', goog.string.toSelectorCase('one'));
  990. assertEquals('one-two', goog.string.toSelectorCase('one-two'));
  991. assertEquals(
  992. 'String value matching a native function name.', 'to-string',
  993. goog.string.toSelectorCase('toString'));
  994. }
  995. function testToTitleCase() {
  996. assertEquals('One', goog.string.toTitleCase('one'));
  997. assertEquals('CamelCase', goog.string.toTitleCase('camelCase'));
  998. assertEquals('Onelongword', goog.string.toTitleCase('onelongword'));
  999. assertEquals('One Two Three', goog.string.toTitleCase('one two three'));
  1000. assertEquals(
  1001. 'One Two Three',
  1002. goog.string.toTitleCase('one two three'));
  1003. assertEquals(' Longword ', goog.string.toTitleCase(' longword '));
  1004. assertEquals('One-two-three', goog.string.toTitleCase('one-two-three'));
  1005. assertEquals('One_two_three', goog.string.toTitleCase('one_two_three'));
  1006. assertEquals(
  1007. 'String value matching a native function name.', 'ToString',
  1008. goog.string.toTitleCase('toString'));
  1009. // Verify results with no delimiter.
  1010. assertEquals('One two three', goog.string.toTitleCase('one two three', ''));
  1011. assertEquals('One-two-three', goog.string.toTitleCase('one-two-three', ''));
  1012. assertEquals(' onetwothree', goog.string.toTitleCase(' onetwothree', ''));
  1013. // Verify results with one delimiter.
  1014. assertEquals('One two', goog.string.toTitleCase('one two', '.'));
  1015. assertEquals(' one two', goog.string.toTitleCase(' one two', '.'));
  1016. assertEquals(' one.Two', goog.string.toTitleCase(' one.two', '.'));
  1017. assertEquals('One.Two', goog.string.toTitleCase('one.two', '.'));
  1018. assertEquals('One...Two...', goog.string.toTitleCase('one...two...', '.'));
  1019. // Verify results with multiple delimiters.
  1020. var delimiters = '_-.';
  1021. assertEquals(
  1022. 'One two three', goog.string.toTitleCase('one two three', delimiters));
  1023. assertEquals(
  1024. ' one two three',
  1025. goog.string.toTitleCase(' one two three', delimiters));
  1026. assertEquals(
  1027. 'One-Two-Three', goog.string.toTitleCase('one-two-three', delimiters));
  1028. assertEquals(
  1029. 'One_Two_Three', goog.string.toTitleCase('one_two_three', delimiters));
  1030. assertEquals(
  1031. 'One...Two...Three',
  1032. goog.string.toTitleCase('one...two...three', delimiters));
  1033. assertEquals(
  1034. 'One. two. three',
  1035. goog.string.toTitleCase('one. two. three', delimiters));
  1036. }
  1037. function testCapitalize() {
  1038. assertEquals('Reptar', goog.string.capitalize('reptar'));
  1039. assertEquals('Reptar reptar', goog.string.capitalize('reptar reptar'));
  1040. assertEquals('Reptar', goog.string.capitalize('REPTAR'));
  1041. assertEquals('Reptar', goog.string.capitalize('Reptar'));
  1042. assertEquals('1234', goog.string.capitalize('1234'));
  1043. assertEquals('$#@!', goog.string.capitalize('$#@!'));
  1044. assertEquals('', goog.string.capitalize(''));
  1045. assertEquals('R', goog.string.capitalize('r'));
  1046. assertEquals('R', goog.string.capitalize('R'));
  1047. }
  1048. function testParseInt() {
  1049. // Many example values borrowed from
  1050. // http://trac.webkit.org/browser/trunk/LayoutTests/fast/js/kde/
  1051. // GlobalObject-expected.txt
  1052. // Check non-numbers and strings
  1053. assertTrue(isNaN(goog.string.parseInt(undefined)));
  1054. assertTrue(isNaN(goog.string.parseInt(null)));
  1055. assertTrue(isNaN(goog.string.parseInt({})));
  1056. assertTrue(isNaN(goog.string.parseInt('')));
  1057. assertTrue(isNaN(goog.string.parseInt(' ')));
  1058. assertTrue(isNaN(goog.string.parseInt('a')));
  1059. assertTrue(isNaN(goog.string.parseInt('FFAA')));
  1060. assertEquals(1, goog.string.parseInt(1));
  1061. assertEquals(1234567890123456, goog.string.parseInt(1234567890123456));
  1062. assertEquals(2, goog.string.parseInt(' 2.3'));
  1063. assertEquals(16, goog.string.parseInt('0x10'));
  1064. assertEquals(11, goog.string.parseInt('11'));
  1065. assertEquals(15, goog.string.parseInt('0xF'));
  1066. assertEquals(15, goog.string.parseInt('0XF'));
  1067. assertEquals(3735928559, goog.string.parseInt('0XDEADBEEF'));
  1068. assertEquals(3, goog.string.parseInt('3x'));
  1069. assertEquals(3, goog.string.parseInt('3 x'));
  1070. assertFalse(isFinite(goog.string.parseInt('Infinity')));
  1071. assertEquals(15, goog.string.parseInt('15'));
  1072. assertEquals(15, goog.string.parseInt('015'));
  1073. assertEquals(15, goog.string.parseInt('0xf'));
  1074. assertEquals(15, goog.string.parseInt('15'));
  1075. assertEquals(15, goog.string.parseInt('0xF'));
  1076. assertEquals(15, goog.string.parseInt('15.99'));
  1077. assertTrue(isNaN(goog.string.parseInt('FXX123')));
  1078. assertEquals(15, goog.string.parseInt('15*3'));
  1079. assertEquals(7, goog.string.parseInt('0x7'));
  1080. assertEquals(1, goog.string.parseInt('1x7'));
  1081. // Strings have no special meaning
  1082. assertTrue(isNaN(goog.string.parseInt('Infinity')));
  1083. assertTrue(isNaN(goog.string.parseInt('NaN')));
  1084. // Test numbers and values
  1085. assertEquals(3, goog.string.parseInt(3.3));
  1086. assertEquals(-3, goog.string.parseInt(-3.3));
  1087. assertEquals(0, goog.string.parseInt(-0));
  1088. assertTrue(isNaN(goog.string.parseInt(Infinity)));
  1089. assertTrue(isNaN(goog.string.parseInt(NaN)));
  1090. assertTrue(isNaN(goog.string.parseInt(Number.POSITIVE_INFINITY)));
  1091. assertTrue(isNaN(goog.string.parseInt(Number.NEGATIVE_INFINITY)));
  1092. // In Chrome (at least), parseInt(Number.MIN_VALUE) is 5 (5e-324) and
  1093. // parseInt(Number.MAX_VALUE) is 1 (1.79...e+308) as they are converted
  1094. // to strings. We do not attempt to correct this behavior.
  1095. // Additional values for negatives.
  1096. assertEquals(-3, goog.string.parseInt('-3'));
  1097. assertEquals(-32, goog.string.parseInt('-32 '));
  1098. assertEquals(-32, goog.string.parseInt(' -32 '));
  1099. assertEquals(-3, goog.string.parseInt('-0x3'));
  1100. assertEquals(-50, goog.string.parseInt('-0x32 '));
  1101. assertEquals(-243, goog.string.parseInt(' -0xF3 '));
  1102. assertTrue(isNaN(goog.string.parseInt(' - 0x32 ')));
  1103. }
  1104. function testIsLowerCamelCase() {
  1105. assertTrue(goog.string.isLowerCamelCase('foo'));
  1106. assertTrue(goog.string.isLowerCamelCase('fooBar'));
  1107. assertTrue(goog.string.isLowerCamelCase('fooBarBaz'));
  1108. assertTrue(goog.string.isLowerCamelCase('innerHTML'));
  1109. assertFalse(goog.string.isLowerCamelCase(''));
  1110. assertFalse(goog.string.isLowerCamelCase('a3a'));
  1111. assertFalse(goog.string.isLowerCamelCase('goog.dom'));
  1112. assertFalse(goog.string.isLowerCamelCase('Foo'));
  1113. assertFalse(goog.string.isLowerCamelCase('FooBar'));
  1114. assertFalse(goog.string.isLowerCamelCase('ABCBBD'));
  1115. }
  1116. function testIsUpperCamelCase() {
  1117. assertFalse(goog.string.isUpperCamelCase(''));
  1118. assertFalse(goog.string.isUpperCamelCase('foo'));
  1119. assertFalse(goog.string.isUpperCamelCase('fooBar'));
  1120. assertFalse(goog.string.isUpperCamelCase('fooBarBaz'));
  1121. assertFalse(goog.string.isUpperCamelCase('innerHTML'));
  1122. assertFalse(goog.string.isUpperCamelCase('a3a'));
  1123. assertFalse(goog.string.isUpperCamelCase('goog.dom'));
  1124. assertFalse(goog.string.isUpperCamelCase('Boyz2Men'));
  1125. assertTrue(goog.string.isUpperCamelCase('ABCBBD'));
  1126. assertTrue(goog.string.isUpperCamelCase('Foo'));
  1127. assertTrue(goog.string.isUpperCamelCase('FooBar'));
  1128. assertTrue(goog.string.isUpperCamelCase('FooBarBaz'));
  1129. }
  1130. function testSplitLimit() {
  1131. assertArrayEquals(['a*a*a*a'], goog.string.splitLimit('a*a*a*a', '*', -1));
  1132. assertArrayEquals(['a*a*a*a'], goog.string.splitLimit('a*a*a*a', '*', 0));
  1133. assertArrayEquals(['a', 'a*a*a'], goog.string.splitLimit('a*a*a*a', '*', 1));
  1134. assertArrayEquals(
  1135. ['a', 'a', 'a*a'], goog.string.splitLimit('a*a*a*a', '*', 2));
  1136. assertArrayEquals(
  1137. ['a', 'a', 'a', 'a'], goog.string.splitLimit('a*a*a*a', '*', 3));
  1138. assertArrayEquals(
  1139. ['a', 'a', 'a', 'a'], goog.string.splitLimit('a*a*a*a', '*', 4));
  1140. assertArrayEquals(
  1141. ['bbbbbbbbbbbb'], goog.string.splitLimit('bbbbbbbbbbbb', 'a', 10));
  1142. assertArrayEquals(
  1143. ['babab', 'bab', 'abb'],
  1144. goog.string.splitLimit('bababaababaaabb', 'aa', 10));
  1145. assertArrayEquals(
  1146. ['babab', 'babaaabb'],
  1147. goog.string.splitLimit('bababaababaaabb', 'aa', 1));
  1148. assertArrayEquals(
  1149. ['b', 'a', 'b', 'a', 'b', 'a', 'a', 'b', 'a', 'b', 'aaabb'],
  1150. goog.string.splitLimit('bababaababaaabb', '', 10));
  1151. }
  1152. function testContains() {
  1153. assertTrue(goog.string.contains('moot', 'moo'));
  1154. assertFalse(goog.string.contains('moo', 'moot'));
  1155. assertFalse(goog.string.contains('Moot', 'moo'));
  1156. assertTrue(goog.string.contains('moo', 'moo'));
  1157. }
  1158. function testCaseInsensitiveContains() {
  1159. assertTrue(goog.string.caseInsensitiveContains('moot', 'moo'));
  1160. assertFalse(goog.string.caseInsensitiveContains('moo', 'moot'));
  1161. assertTrue(goog.string.caseInsensitiveContains('Moot', 'moo'));
  1162. assertTrue(goog.string.caseInsensitiveContains('moo', 'moo'));
  1163. }
  1164. function testEditDistance() {
  1165. assertEquals(
  1166. 'Empty string should match to length of other string', 4,
  1167. goog.string.editDistance('goat', ''));
  1168. assertEquals(
  1169. 'Empty string should match to length of other string', 4,
  1170. goog.string.editDistance('', 'moat'));
  1171. assertEquals(
  1172. 'Equal strings should have zero edit distance', 0,
  1173. goog.string.editDistance('abcd', 'abcd'));
  1174. assertEquals(
  1175. 'Equal strings should have zero edit distance', 0,
  1176. goog.string.editDistance('', ''));
  1177. assertEquals(
  1178. 'Edit distance for adding characters incorrect', 4,
  1179. goog.string.editDistance('bdf', 'abcdefg'));
  1180. assertEquals(
  1181. 'Edit distance for removing characters incorrect', 4,
  1182. goog.string.editDistance('abcdefg', 'bdf'));
  1183. assertEquals(
  1184. 'Edit distance for substituting characters incorrect', 4,
  1185. goog.string.editDistance('adef', 'ghij'));
  1186. assertEquals(
  1187. 'Edit distance for substituting characters incorrect', 1,
  1188. goog.string.editDistance('goat', 'boat'));
  1189. assertEquals(
  1190. 'Substitution should be preferred over insert/delete', 4,
  1191. goog.string.editDistance('abcd', 'defg'));
  1192. }
  1193. function testLastComponent() {
  1194. assertEquals(
  1195. 'Last component of a string without separators should be the string',
  1196. 'abcdefgh', goog.string.lastComponent('abcdefgh', []));
  1197. assertEquals(
  1198. 'Last component of a string without separators should be the string',
  1199. 'abcdefgh', goog.string.lastComponent('abcdefgh', null));
  1200. assertEquals(
  1201. 'Last component of a string without separators should be the string',
  1202. 'abcdefgh', goog.string.lastComponent('abcdefgh', undefined));
  1203. assertEquals(
  1204. 'Last component of a string without separators should be the string',
  1205. 'abcdefgh', goog.string.lastComponent('abcdefgh', ''));
  1206. assertEquals(
  1207. 'Giving a simple string separator instead of an array should work', 'fgh',
  1208. goog.string.lastComponent('abcdefgh', 'e'));
  1209. assertEquals(
  1210. 'Last component of a string without separators should be the string',
  1211. 'abcdefgh', goog.string.lastComponent('abcdefgh', ['']));
  1212. assertEquals(
  1213. 'Last component of a string without separators should be the string',
  1214. 'abcdefgh', goog.string.lastComponent('abcdefgh', ['', '']));
  1215. assertEquals(
  1216. 'Last component of a string without separators should be the string',
  1217. 'abcdefgh', goog.string.lastComponent('abcdefgh', ['']));
  1218. assertEquals(
  1219. 'Last component of a single character string should be the string', 'a',
  1220. goog.string.lastComponent('a', ['']));
  1221. assertEquals(
  1222. 'Last component of a single character string separated by its only' +
  1223. 'character should be the empty string',
  1224. '', goog.string.lastComponent('a', ['a']));
  1225. assertEquals(
  1226. 'Last component of the empty string should be the empty string', '',
  1227. goog.string.lastComponent('', ['']));
  1228. assertEquals(
  1229. 'Last component of the empty string should be the empty string', '',
  1230. goog.string.lastComponent('', ['a']));
  1231. assertEquals(
  1232. 'Last component of the empty string should be the empty string', '',
  1233. goog.string.lastComponent('', ['']));
  1234. assertEquals('ccc', goog.string.lastComponent('aaabbbccc', ['b']));
  1235. assertEquals('baz', goog.string.lastComponent('foo/bar/baz', ['/']));
  1236. assertEquals('baz', goog.string.lastComponent('foo.bar.baz', ['.']));
  1237. assertEquals('baz', goog.string.lastComponent('foo.bar.baz', ['/', '.']));
  1238. assertEquals('bar/baz', goog.string.lastComponent('foo.bar/baz', ['.']));
  1239. assertEquals('bar-baz', goog.string.lastComponent('foo.bar-baz', ['/', '.']));
  1240. assertEquals('baz', goog.string.lastComponent('foo.bar-baz', ['-', '', '.']));
  1241. }