template_expressions_unittest.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/base/template_expressions.h"
  5. #include "base/test/gtest_util.h"
  6. #include "testing/gtest/include/gtest/gtest.h"
  7. namespace ui {
  8. // Tip: ui_base_unittests --gtest_filter='TemplateExpressionsTest.*' to run
  9. // these tests.
  10. TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsPieces) {
  11. TemplateReplacements substitutions;
  12. substitutions["test"] = "word";
  13. substitutions["5"] = "number";
  14. EXPECT_EQ("", ReplaceTemplateExpressions("", substitutions));
  15. EXPECT_EQ("word", ReplaceTemplateExpressions("$i18n{test}", substitutions));
  16. EXPECT_EQ("number ", ReplaceTemplateExpressions("$i18n{5} ", substitutions));
  17. EXPECT_EQ("multiple: word, number.",
  18. ReplaceTemplateExpressions("multiple: $i18n{test}, $i18n{5}.",
  19. substitutions));
  20. }
  21. TEST(TemplateExpressionsTest,
  22. ReplaceTemplateExpressionsConsecutiveDollarSignsPieces) {
  23. TemplateReplacements substitutions;
  24. substitutions["a"] = "x";
  25. EXPECT_EQ("$ $$ $$$", ReplaceTemplateExpressions("$ $$ $$$", substitutions));
  26. EXPECT_EQ("$x", ReplaceTemplateExpressions("$$i18n{a}", substitutions));
  27. EXPECT_EQ("$$x", ReplaceTemplateExpressions("$$$i18n{a}", substitutions));
  28. EXPECT_EQ("$i1812", ReplaceTemplateExpressions("$i1812", substitutions));
  29. }
  30. TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsEscaping) {
  31. static TemplateReplacements substitutions;
  32. substitutions["punctuationSample"] = "a\"b'c<d>e&f";
  33. substitutions["htmlSample"] = "<div>hello</div>";
  34. EXPECT_EQ(
  35. "a&quot;b&#39;c&lt;d&gt;e&amp;f",
  36. ReplaceTemplateExpressions("$i18n{punctuationSample}", substitutions));
  37. EXPECT_EQ("&lt;div&gt;hello&lt;/div&gt;",
  38. ReplaceTemplateExpressions("$i18n{htmlSample}", substitutions));
  39. EXPECT_EQ(
  40. "multiple: &lt;div&gt;hello&lt;/div&gt;, a&quot;b&#39;c&lt;d&gt;e&amp;f.",
  41. ReplaceTemplateExpressions(
  42. "multiple: $i18n{htmlSample}, $i18n{punctuationSample}.",
  43. substitutions));
  44. }
  45. TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsRaw) {
  46. static TemplateReplacements substitutions;
  47. substitutions["rawSample"] = "<a href=\"example.com\">hello</a>";
  48. EXPECT_EQ("<a href=\"example.com\">hello</a>",
  49. ReplaceTemplateExpressions("$i18nRaw{rawSample}", substitutions));
  50. }
  51. TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsSkipPlaceholderCheck) {
  52. static TemplateReplacements substitutions;
  53. substitutions["rawSample"] = "$1";
  54. // Skips DCHECK if |skip_unexpected_placeholder_check| is true.
  55. ReplaceTemplateExpressions("$i18nRaw{rawSample}", substitutions,
  56. /* skip_unexpected_placeholder_check= */ true);
  57. EXPECT_DCHECK_DEATH(ReplaceTemplateExpressions(
  58. "$i18nRaw{rawSample}", substitutions,
  59. /* skip_unexpected_placeholder_check= */ false));
  60. // |skip_unexpected_placeholder_check|'s default value is false.
  61. EXPECT_DCHECK_DEATH(
  62. ReplaceTemplateExpressions("$i18nRaw{rawSample}", substitutions));
  63. }
  64. TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsPolymerQuoting) {
  65. static TemplateReplacements substitutions;
  66. substitutions["singleSample"] = "don't do it";
  67. substitutions["doubleSample"] = "\"moo\" said the cow";
  68. // This resolves |Call('don\'t do it')| to Polymer, which is presented as
  69. // |don't do it| to the user.
  70. EXPECT_EQ("<div>[[Call('don\\'t do it')]]",
  71. ReplaceTemplateExpressions(
  72. "<div>[[Call('$i18nPolymer{singleSample}')]]", substitutions));
  73. // This resolves |Call('\"moo\" said the cow')| to Polymer, which is
  74. // presented as |"moo" said the cow| to the user.
  75. EXPECT_EQ("<div>[[Call('&quot;moo&quot; said the cow')]]",
  76. ReplaceTemplateExpressions(
  77. "<div>[[Call('$i18nPolymer{doubleSample}')]]", substitutions));
  78. }
  79. TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsPolymerMixed) {
  80. static TemplateReplacements substitutions;
  81. substitutions["punctuationSample"] = R"(a"b'c<d>e&f,g)";
  82. substitutions["htmlSample"] = "<div>hello</div>";
  83. EXPECT_EQ(R"(a&quot;b\'c<d>e&f\,g)",
  84. ReplaceTemplateExpressions("$i18nPolymer{punctuationSample}",
  85. substitutions));
  86. EXPECT_EQ("<div>hello</div>", ReplaceTemplateExpressions(
  87. "$i18nPolymer{htmlSample}", substitutions));
  88. EXPECT_EQ(R"(multiple: <div>hello</div>, a&quot;b\'c<d>e&f\,g.)",
  89. ReplaceTemplateExpressions("multiple: $i18nPolymer{htmlSample}, "
  90. "$i18nPolymer{punctuationSample}.",
  91. substitutions));
  92. }
  93. struct TestCase {
  94. const char* js_in;
  95. const char* expected_out;
  96. };
  97. TEST(TemplateExpressionsTest, JSNoReplacementOutsideTemplate) {
  98. TemplateReplacements substitutions;
  99. substitutions["test"] = "word";
  100. substitutions["5"] = "number";
  101. const TestCase kTestCases[] = {
  102. // No substitutions should occur in normal JS code.
  103. {"console.log('hello world');", "console.log('hello world');"},
  104. // Has HTML content but nothing to substitute.
  105. {"Polymer({\n"
  106. " _template: html`<!--_html_template_start_-->\n"
  107. " <button on-click=\"onClick_\">Button Name</button>\n"
  108. "<!--_html_template_end_-->`,\n"
  109. " is: 'foo-element',\n"
  110. " onClick_: function() { console.log('hello'); },\n"
  111. "});",
  112. "Polymer({\n"
  113. " _template: html`<!--_html_template_start_-->\n"
  114. " <button on-click=\"onClick_\">Button Name</button>\n"
  115. "<!--_html_template_end_-->`,\n"
  116. " is: 'foo-element',\n"
  117. " onClick_: function() { console.log('hello'); },\n"
  118. "});"},
  119. // Basic substitution with template on 1 line.
  120. {"Polymer({\n"
  121. " _template: html`<!--_html_template_start_-->\n"
  122. "<div>$i18n{test}</div><!--_html_template_end_-->`,\n"
  123. " is: 'foo-element',\n"
  124. "});",
  125. "Polymer({\n"
  126. " _template: html`<!--_html_template_start_-->\n"
  127. "<div>word</div><!--_html_template_end_-->`,\n"
  128. " is: 'foo-element',\n"
  129. "});"},
  130. // No replacement if start/end comments are missing.
  131. {"Polymer({\n"
  132. " _template: html`<div>$i18n{test}</div>`,\n"
  133. " is: 'foo-element',\n"
  134. "});",
  135. "Polymer({\n"
  136. " _template: html`<div>$i18n{test}</div>`,\n"
  137. " is: 'foo-element',\n"
  138. "});"},
  139. // No replacement outside start/end comments, even if inside the HTML
  140. // _template string.
  141. {"Polymer({\n"
  142. " _template: $i18n{test} html`$i18n{5}<!--_html_template_start_-->"
  143. "<div>Hello</div><!--_html_template_end_-->$i18n{test}`,\n"
  144. " is: 'foo-element',\n"
  145. "});",
  146. "Polymer({\n"
  147. " _template: $i18n{test} html`$i18n{5}<!--_html_template_start_-->"
  148. "<div>Hello</div><!--_html_template_end_-->$i18n{test}`,\n"
  149. " is: 'foo-element',\n"
  150. "});"},
  151. // Test case in which only the first $i18n{...} should be substituted,
  152. // since the second is not in the HTML template string.
  153. {"Polymer({\n"
  154. " _template: html`\n"
  155. "<!--_html_template_start_-->\n"
  156. " <button on-click=\"onClick_\">$i18n{test}</button>\n"
  157. "<!--_html_template_end_-->\n"
  158. " `,\n"
  159. " is: 'foo-element',\n"
  160. " onClick_: function() { console.log($i18n{5}); },\n"
  161. "});",
  162. "Polymer({\n"
  163. " _template: html`\n"
  164. "<!--_html_template_start_-->\n"
  165. " <button on-click=\"onClick_\">word</button>\n"
  166. "<!--_html_template_end_-->\n"
  167. " `,\n"
  168. " is: 'foo-element',\n"
  169. " onClick_: function() { console.log($i18n{5}); },\n"
  170. "});"},
  171. // Test case with multiple valid substitutions.
  172. {"Polymer({\n"
  173. " _template: html`\n"
  174. "<!--_html_template_start_-->\n"
  175. " <button on-click=\"onClick_\">$i18n{test}</button>\n"
  176. " <span>$i18n{5}</span>\n"
  177. "<!--_html_template_end_-->\n"
  178. " `,\n"
  179. " is: 'foo-element',\n"
  180. " onClick_: function() { console.log('hello'); },\n"
  181. "});",
  182. "Polymer({\n"
  183. " _template: html`\n"
  184. "<!--_html_template_start_-->\n"
  185. " <button on-click=\"onClick_\">word</button>\n"
  186. " <span>number</span>\n"
  187. "<!--_html_template_end_-->\n"
  188. " `,\n"
  189. " is: 'foo-element',\n"
  190. " onClick_: function() { console.log('hello'); },\n"
  191. "});"}};
  192. std::string formatted;
  193. for (const TestCase test_case : kTestCases) {
  194. ASSERT_TRUE(ReplaceTemplateExpressionsInJS(test_case.js_in, substitutions,
  195. &formatted));
  196. EXPECT_EQ(test_case.expected_out, formatted);
  197. formatted.clear();
  198. }
  199. }
  200. TEST(TemplateExpressionsTest, JSReplacementsEscape) {
  201. TemplateReplacements substitutions;
  202. substitutions["backtickSample"] =
  203. "`, attached: function() { alert(1); },_template: html`";
  204. substitutions["dollarSignSample"] = "5$";
  205. substitutions["punctuationSample"] = "a\"b'c<d>e&f";
  206. substitutions["htmlSample"] = "<div>hello</div>";
  207. const TestCase kTestCases[] = {
  208. // Substitution with a backtick in the replacement.
  209. {"Polymer({\n"
  210. " _template: html`\n"
  211. "<!--_html_template_start_-->\n"
  212. " <span>\n"
  213. " $i18n{backtickSample}\n"
  214. " </span>\n"
  215. " <button on-click=\"onClick_\">Button</button>\n"
  216. "<!--_html_template_end_-->\n"
  217. " `,\n"
  218. " is: 'foo-element',\n"
  219. " onClick_: function() { console.log('hello'); },\n"
  220. "});",
  221. "Polymer({\n"
  222. " _template: html`\n"
  223. "<!--_html_template_start_-->\n"
  224. " <span>\n"
  225. " \\`, attached: function() { alert(1); },_template: html\\`\n"
  226. " </span>\n"
  227. " <button on-click=\"onClick_\">Button</button>\n"
  228. "<!--_html_template_end_-->\n"
  229. " `,\n"
  230. " is: 'foo-element',\n"
  231. " onClick_: function() { console.log('hello'); },\n"
  232. "});"},
  233. // Backtick in one replacement, HTML escapes in other replacements. Class
  234. // based syntax.
  235. {"class FooElement extends PolymerElement {\n"
  236. " static get template() {\n"
  237. " return html`<!--_html_template_start_--><span>\n"
  238. " $i18n{backtickSample}\n"
  239. " </span>\n"
  240. " <button on-click=\"onClick_\">\n"
  241. " $i18n{punctuationSample}.\n"
  242. " </button>\n"
  243. " <div>$i18n{htmlSample}</div><!--_html_template_end_-->`;\n"
  244. " }\n"
  245. " static get is() {\n"
  246. " return 'foo-element';\n"
  247. " }\n"
  248. " onClick_() { console.log('hello'); }\n"
  249. "};",
  250. "class FooElement extends PolymerElement {\n"
  251. " static get template() {\n"
  252. " return html`<!--_html_template_start_--><span>\n"
  253. " \\`, attached: function() { alert(1); },_template: html\\`\n"
  254. " </span>\n"
  255. " <button on-click=\"onClick_\">\n"
  256. " a&quot;b&#39;c&lt;d&gt;e&amp;f.\n"
  257. " </button>\n"
  258. " <div>&lt;div&gt;hello&lt;/div&gt;</div>"
  259. "<!--_html_template_end_-->`;\n"
  260. " }\n"
  261. " static get is() {\n"
  262. " return 'foo-element';\n"
  263. " }\n"
  264. " onClick_() { console.log('hello'); }\n"
  265. "};"},
  266. // Replacement contains a '$' that isn't accompanied by a subsequent '{',
  267. // so should be replaced correctly.
  268. {"Polymer({\n"
  269. " _template: html`\n"
  270. "<!--_html_template_start_-->\n"
  271. " <div>Price is: $i18n{dollarSignSample}</div>\n"
  272. "<!--_html_template_end_-->\n"
  273. " `,\n"
  274. " is: 'foo-element',\n"
  275. "});",
  276. "Polymer({\n"
  277. " _template: html`\n"
  278. "<!--_html_template_start_-->\n"
  279. " <div>Price is: 5$</div>\n"
  280. "<!--_html_template_end_-->\n"
  281. " `,\n"
  282. " is: 'foo-element',\n"
  283. "});"}};
  284. std::string formatted;
  285. for (const TestCase test_case : kTestCases) {
  286. ASSERT_TRUE(ReplaceTemplateExpressionsInJS(test_case.js_in, substitutions,
  287. &formatted));
  288. EXPECT_EQ(test_case.expected_out, formatted);
  289. formatted.clear();
  290. }
  291. }
  292. TEST(TemplateExpressionsTest, JSReplacementsError) {
  293. TemplateReplacements substitutions;
  294. substitutions["test"] = "${foo + bar}";
  295. substitutions["testa"] = "5$";
  296. substitutions["testb"] = "{a + b}";
  297. // All these cases should fail.
  298. const TestCase kTestCases[] = {
  299. // Nested templates not allowed.
  300. {"class FooElement extends PolymerElement {\n"
  301. " static get template() { return html`\n"
  302. "<!--_html_template_start_-->\n"
  303. " _template: html`\n"
  304. "<!--_html_template_start_-->\n"
  305. " <span>Hello</span>\n"
  306. "<!--_html_template_end_-->\n"
  307. " `,\n"
  308. " <div>World</div>\n"
  309. "<!--_html_template_end_-->\n"
  310. " `;}\n"
  311. " static get is() { return 'foo-element'; }\n"
  312. "};",
  313. ""},
  314. // 2 starts, one end.
  315. {"Polymer({\n"
  316. " _template: html`\n"
  317. "<!--_html_template_start_-->\n"
  318. " _template: html`\n"
  319. "<!--_html_template_start_-->\n"
  320. " <span>Hello</span>\n"
  321. " <div>World</div>\n"
  322. "<!--_html_template_end_-->\n"
  323. " `,\n"
  324. " is: 'foo-element',\n"
  325. "});",
  326. ""},
  327. // Replacement contains "${".
  328. {"class FooElement extends PolymerElement {\n"
  329. " static get template() { return html`\n"
  330. "<!--_html_template_start_-->\n"
  331. " <div>$i18n{test}</div>\n"
  332. "<!--_html_template_end_-->`;\n"
  333. " }\n"
  334. " static get is() { return 'foo-element'; }\n"
  335. "};",
  336. ""},
  337. // 2 replacements, when combined, create "${".
  338. {"Polymer({\n"
  339. " _template: html`\n"
  340. "<!--_html_template_start_-->\n"
  341. " <div>$i18n{testa}$i18n{testb}</div>\n"
  342. "<!--_html_template_end_-->\n"
  343. " `,\n"
  344. " is: 'foo-element',\n"
  345. "});",
  346. ""},
  347. // Replacement, when combined with content preceding it, creates "${".
  348. {"class FooElement extends PolymerElement {\n"
  349. " static get template() { return html`\n"
  350. "<!--_html_template_start_-->\n"
  351. " <div>Price is: $$i18n{testb}</div>\n"
  352. "<!--_html_template_end_-->\n"
  353. " `;}\n"
  354. " static get is() {return 'foo-element'; }\n"
  355. "};",
  356. ""},
  357. // HTML _template string is not terminated.
  358. {"Polymer({\n"
  359. " _template: html`\n"
  360. "<!--_html_template_start_-->\n"
  361. " <div>Price is: $i18n{testa}</div>\n"
  362. "<!--_html_template_not_end-->\n"
  363. " is: 'foo-element',\n"
  364. "});",
  365. ""},
  366. };
  367. std::string formatted;
  368. for (const TestCase test_case : kTestCases) {
  369. ASSERT_FALSE(ReplaceTemplateExpressionsInJS(test_case.js_in, substitutions,
  370. &formatted));
  371. formatted.clear();
  372. }
  373. }
  374. TEST(TemplateExpressionsTest, JSMultipleTemplates) {
  375. TemplateReplacements substitutions;
  376. substitutions["test"] = "word";
  377. substitutions["5"] = "number";
  378. const TestCase kTestCases[] = {
  379. // Only the second template has substitutions
  380. {"Polymer({\n"
  381. " _template: html`<!--_html_template_start_-->\n"
  382. " <div>Hello</div>\n"
  383. "<!--_html_template_end_-->`,\n"
  384. " is: 'foo-element',\n"
  385. "});"
  386. "Polymer({\n"
  387. " _template: html`<!--_html_template_start_-->\n"
  388. " <div>$i18n{5}$i18n{test}</div>\n"
  389. "<!--_html_template_end_-->`,\n"
  390. " is: 'bar-element',\n"
  391. "});",
  392. "Polymer({\n"
  393. " _template: html`<!--_html_template_start_-->\n"
  394. " <div>Hello</div>\n"
  395. "<!--_html_template_end_-->`,\n"
  396. " is: 'foo-element',\n"
  397. "});"
  398. "Polymer({\n"
  399. " _template: html`<!--_html_template_start_-->\n"
  400. " <div>numberword</div>\n"
  401. "<!--_html_template_end_-->`,\n"
  402. " is: 'bar-element',\n"
  403. "});"},
  404. // 2 templates, both with substitutions.
  405. {"Polymer({\n"
  406. " _template: html`<!--_html_template_start_-->\n"
  407. " <div>$i18n{test}</div>\n"
  408. "<!--_html_template_end_-->`,\n"
  409. " is: 'foo-element',\n"
  410. "});"
  411. "Polymer({\n"
  412. " _template: html`<!--_html_template_start_-->\n"
  413. " <div>$i18n{5}</div>\n"
  414. "<!--_html_template_end_-->`,\n"
  415. " is: 'bar-element',\n"
  416. "});",
  417. "Polymer({\n"
  418. " _template: html`<!--_html_template_start_-->\n"
  419. " <div>word</div>\n"
  420. "<!--_html_template_end_-->`,\n"
  421. " is: 'foo-element',\n"
  422. "});"
  423. "Polymer({\n"
  424. " _template: html`<!--_html_template_start_-->\n"
  425. " <div>number</div>\n"
  426. "<!--_html_template_end_-->`,\n"
  427. " is: 'bar-element',\n"
  428. "});"},
  429. // 2 class based templates
  430. {"class FooElement extends PolymerElement {\n"
  431. " static get template() {\n"
  432. " return html`<!--_html_template_start_-->\n"
  433. " <div>$i18n{test}</div>\n"
  434. "<!--_html_template_end_-->`;\n"
  435. " }\n"
  436. " static get is() {\n"
  437. " return 'foo-element';\n"
  438. " }\n"
  439. "};\n"
  440. "class BarElement extends PolymerElement {\n"
  441. " static get template() {\n"
  442. " return html`<!--_html_template_start_-->\n"
  443. " <div>$i18n{5}</div>\n"
  444. "<!--_html_template_end_-->`;\n"
  445. " }\n"
  446. " static get is() {\n"
  447. " return 'bar-element';\n"
  448. " }\n"
  449. "};",
  450. "class FooElement extends PolymerElement {\n"
  451. " static get template() {\n"
  452. " return html`<!--_html_template_start_-->\n"
  453. " <div>word</div>\n"
  454. "<!--_html_template_end_-->`;\n"
  455. " }\n"
  456. " static get is() {\n"
  457. " return 'foo-element';\n"
  458. " }\n"
  459. "};\n"
  460. "class BarElement extends PolymerElement {\n"
  461. " static get template() {\n"
  462. " return html`<!--_html_template_start_-->\n"
  463. " <div>number</div>\n"
  464. "<!--_html_template_end_-->`;\n"
  465. " }\n"
  466. " static get is() {\n"
  467. " return 'bar-element';\n"
  468. " }\n"
  469. "};"},
  470. // One element has no UI.
  471. {"Polymer({\n"
  472. " _template: null,\n"
  473. " is: 'bar-element',\n"
  474. "});\n"
  475. "Polymer({\n"
  476. " _template: html`\n"
  477. "<!--_html_template_start_-->\n"
  478. " <button on-click=\"onClick_\">$i18n{test}</button>\n"
  479. "<!--_html_template_end_-->\n"
  480. " `,\n"
  481. " is: 'foo-element',\n"
  482. " onClick_: function() { console.log('hello'); },\n"
  483. "});",
  484. "Polymer({\n"
  485. " _template: null,\n"
  486. " is: 'bar-element',\n"
  487. "});\n"
  488. "Polymer({\n"
  489. " _template: html`\n"
  490. "<!--_html_template_start_-->\n"
  491. " <button on-click=\"onClick_\">word</button>\n"
  492. "<!--_html_template_end_-->\n"
  493. " `,\n"
  494. " is: 'foo-element',\n"
  495. " onClick_: function() { console.log('hello'); },\n"
  496. "});"},
  497. // One element only has a template (e.g. style), with class based syntax.
  498. {"class StyleElement extends PolymerElement {\n"
  499. " static get template() {return html`<!--_html_template_start_-->\n"
  500. "<div></div><!--_html_template_end_-->`;}\n"
  501. "};\n"
  502. "class FooElement extends PolymerElement {\n"
  503. " static get template() {\n"
  504. " return html`<!--_html_template_start_-->\n"
  505. " <button on-click=\"onClick_\">$i18n{test}</button>\n"
  506. " <!--_html_template_end_-->`;\n"
  507. " }\n"
  508. " static get is() { return 'foo-element'; }\n"
  509. " onClick_() { console.log('hello'); }\n"
  510. "};",
  511. "class StyleElement extends PolymerElement {\n"
  512. " static get template() {return html`<!--_html_template_start_-->\n"
  513. "<div></div><!--_html_template_end_-->`;}\n"
  514. "};\n"
  515. "class FooElement extends PolymerElement {\n"
  516. " static get template() {\n"
  517. " return html`<!--_html_template_start_-->\n"
  518. " <button on-click=\"onClick_\">word</button>\n"
  519. " <!--_html_template_end_-->`;\n"
  520. " }\n"
  521. " static get is() { return 'foo-element'; }\n"
  522. " onClick_() { console.log('hello'); }\n"
  523. "};"},
  524. // 2 minified templates, both with substitutions.
  525. {"Polymer({_template:html`<!--_html_template_start_--><div>$i18n{test}"
  526. "</div><!--_html_template_end_-->`,is:'foo-element',}); "
  527. "Polymer({_template:html`<!--_html_template_start_--><div>$i18n{5}"
  528. "</div><!--_html_template_end_-->`,is:'bar-element',});",
  529. "Polymer({_template:html`<!--_html_template_start_--><div>word</div>"
  530. "<!--_html_template_end_-->`,is:'foo-element',}); "
  531. "Polymer({_template:html`<!--_html_template_start_--><div>number</div>"
  532. "<!--_html_template_end_-->`,is:'bar-element',});"},
  533. {"class FooElement extends PolymerElement {"
  534. "static get template(){return html`<!--_html_template_start_-->"
  535. "<div>$i18n{test}</div><!--_html_template_end_-->`;} "
  536. "static get is(){return 'foo-element';}};\n"
  537. "Polymer({_template:html`<!--_html_template_start_--><div>$i18n{5}"
  538. "</div><!--_html_template_end_-->`,is:'bar-element',});",
  539. "class FooElement extends PolymerElement {"
  540. "static get template(){return html`<!--_html_template_start_-->"
  541. "<div>word</div><!--_html_template_end_-->`;} "
  542. "static get is(){return 'foo-element';}};\n"
  543. "Polymer({_template:html`<!--_html_template_start_--><div>number</div>"
  544. "<!--_html_template_end_-->`,is:'bar-element',});"}};
  545. std::string formatted;
  546. for (const TestCase test_case : kTestCases) {
  547. ASSERT_TRUE(ReplaceTemplateExpressionsInJS(test_case.js_in, substitutions,
  548. &formatted));
  549. EXPECT_EQ(test_case.expected_out, formatted);
  550. formatted.clear();
  551. }
  552. }
  553. TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsPolymerQuotingJS) {
  554. static TemplateReplacements substitutions;
  555. substitutions["quotesAndCommas"] = R"(don't "moo", they said)";
  556. substitutions["backslashes"] = R"(\ \\ \n \r \t \b \f \0)";
  557. const TestCase kTestCases[] = {
  558. // Case: quotesAndCommas
  559. {R"(<!--_html_template_start_-->
  560. <div>[[Call('$i18nPolymer{quotesAndCommas}')]]</div>
  561. <!--_html_template_end_-->)",
  562. R"(<!--_html_template_start_-->
  563. <div>[[Call('don\\'t &quot;moo&quot;\\, they said')]]</div>
  564. <!--_html_template_end_-->)"},
  565. // Case: backslashes
  566. {R"(<!--_html_template_start_-->
  567. <div>[[Call('$i18nPolymer{backslashes}')]]</div>
  568. <!--_html_template_end_-->)",
  569. R"(<!--_html_template_start_-->
  570. <div>[[Call('\\\\ \\\\\\\\ \\\\n \\\\r \\\\t \\\\b \\\\f \\\\0')]]</div>
  571. <!--_html_template_end_-->)"},
  572. };
  573. std::string formatted;
  574. for (const TestCase test_case : kTestCases) {
  575. ASSERT_TRUE(ReplaceTemplateExpressionsInJS(test_case.js_in, substitutions,
  576. &formatted));
  577. EXPECT_EQ(test_case.expected_out, formatted);
  578. formatted.clear();
  579. }
  580. }
  581. } // namespace ui