filters.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. describe('Filters', function() {
  2. let $filter;
  3. // Ignoring page reload request
  4. beforeAll(() => window.onbeforeunload = () => null);
  5. let webClientServiceMock = {
  6. me: {
  7. id: 'MEMEMEME',
  8. displayName: 'Er'
  9. },
  10. contacts: {
  11. get: function(id) {
  12. if (id === 'AAAAAAAA') {
  13. return {
  14. id: 'AAAAAAAA',
  15. displayName: 'ContactA'
  16. }
  17. }
  18. else if (id === 'XXXXXXXX') {
  19. return {
  20. id: 'XXXXXXXX',
  21. displayName: 'ContactX'
  22. }
  23. }
  24. else if (id === '*AAAAAAA') {
  25. return {
  26. id: '*AAAAAAA',
  27. displayName: 'GWContactA'
  28. }
  29. }
  30. else if (id === 'BAD0BAD1') {
  31. return {
  32. id: 'BAD0BAD1',
  33. displayName: '<b>< script >foo&ndash;</b>< script>',
  34. }
  35. }
  36. return null;
  37. }
  38. }
  39. };
  40. let translationMock = {
  41. instant: function(label) {
  42. return label;
  43. }
  44. };
  45. beforeEach(function() {
  46. module('3ema.services');
  47. module('3ema.filters');
  48. module(($provide) => {
  49. $provide.value('WebClientService', webClientServiceMock);
  50. $provide.value('$translate', translationMock);
  51. $provide.constant('$state', null);
  52. });
  53. // Inject the $filter function
  54. inject(function(_$filter_) {
  55. $filter = _$filter_;
  56. });
  57. });
  58. function testPatterns(filterName, cases) {
  59. const filter = $filter(filterName);
  60. for (let testcase of cases) {
  61. const input = testcase[0];
  62. const expected = testcase[1];
  63. expect(filter(input)).toEqual(expected);
  64. };
  65. };
  66. describe('escapeHtml', function() {
  67. this.testPatterns = (cases) => testPatterns('escapeHtml', cases);
  68. it('escapes html tags', () => {
  69. this.testPatterns([
  70. ['<h1>heading</h1>', '&lt;h1&gt;heading&lt;/h1&gt;'],
  71. ['<b>< script >foo&ndash;</b>< script>', '&lt;b&gt;&lt; script &gt;foo&amp;ndash;&lt;/b&gt;&lt; script&gt;'],
  72. ['<a href="/">a</a>', '&lt;a href=&quot;/&quot;&gt;a&lt;/a&gt;'],
  73. ]);
  74. });
  75. });
  76. describe('mentionify', function() {
  77. this.testPatterns = (cases) => testPatterns('mentionify', cases);
  78. it('no mentions', () => {
  79. this.testPatterns([
  80. ['', ''],
  81. ['hello my friend', 'hello my friend'],
  82. ['@[AAAAAAA]', '@[AAAAAAA]'],
  83. ['this is not a valid @[AAAAAAA]', 'this is not a valid @[AAAAAAA]'],
  84. ['@[@@@@@@@]', '@[@@@@@@@]'],
  85. ['this is not a valid @[@@@@@@@]', 'this is not a valid @[@@@@@@@]'],
  86. ]);
  87. });
  88. it('mention - no contacts', () => {
  89. this.testPatterns([
  90. ['@[BBBBBBBB]', '@[BBBBBBBB]'],
  91. ['@[*BBBBBBB]', '@[*BBBBBBB]'],
  92. ]);
  93. });
  94. it('mention - contact', () => {
  95. this.testPatterns([
  96. ['@[AAAAAAAA]', '<span class="mention id AAAAAAAA" text="@[AAAAAAAA]">ContactA</span>'],
  97. ['hello @[AAAAAAAA]. @[AAAAAAAA] you are my friend', 'hello <span class="mention id AAAAAAAA" text="@[AAAAAAAA]">ContactA</span>. <span class="mention id AAAAAAAA" text="@[AAAAAAAA]">ContactA</span> you are my friend'],
  98. ['@[AAAAAAAA] @[AAAAAAAA] @[AAAAAAAA]', '<span class="mention id AAAAAAAA" text="@[AAAAAAAA]">ContactA</span> <span class="mention id AAAAAAAA" text="@[AAAAAAAA]">ContactA</span> <span class="mention id AAAAAAAA" text="@[AAAAAAAA]">ContactA</span>']
  99. ]);
  100. });
  101. it('mention - all', () => {
  102. this.testPatterns([
  103. ['@[@@@@@@@@]', '<span class="mention all" text="@[@@@@@@@@]">messenger.ALL</span>'],
  104. ['@[@@@@@@@@] your base are belong to us', '<span class="mention all" text="@[@@@@@@@@]">messenger.ALL</span> your base are belong to us'],
  105. ['@[@@@@@@@@] @[@@@@@@@@] @[@@@@@@@@]', '<span class="mention all" text="@[@@@@@@@@]">messenger.ALL</span> <span class="mention all" text="@[@@@@@@@@]">messenger.ALL</span> <span class="mention all" text="@[@@@@@@@@]">messenger.ALL</span>']
  106. ]);
  107. });
  108. it('mention - mixed', () => {
  109. this.testPatterns([
  110. ['@[@@@@@@@@] @[AAAAAAAA] @[BBBBBBBB]', '<span class="mention all" text="@[@@@@@@@@]">messenger.ALL</span> <span class="mention id AAAAAAAA" text="@[AAAAAAAA]">ContactA</span> @[BBBBBBBB]'],
  111. ]);
  112. });
  113. it('mention - me contact', () => {
  114. this.testPatterns([
  115. ['@[MEMEMEME]', '<span class="mention me" text="@[MEMEMEME]">Er</span>'],
  116. ['hello @[MEMEMEME]. @[MEMEMEME] you are my friend', 'hello <span class="mention me" text="@[MEMEMEME]">Er</span>. <span class="mention me" text="@[MEMEMEME]">Er</span> you are my friend'],
  117. ['@[MEMEMEME] @[MEMEMEME] @[MEMEMEME]', '<span class="mention me" text="@[MEMEMEME]">Er</span> <span class="mention me" text="@[MEMEMEME]">Er</span> <span class="mention me" text="@[MEMEMEME]">Er</span>']
  118. ]);
  119. });
  120. it('mention - escape html parameters', () => {
  121. this.testPatterns([
  122. ['@[BAD0BAD1]', '<span class="mention id BAD0BAD1" text="@[BAD0BAD1]">&lt;b&gt;&lt; script &gt;foo&amp;ndash;&lt;/b&gt;&lt; script&gt;</span>'],
  123. ]);
  124. });
  125. });
  126. describe('nlToBr', function() {
  127. this.testPatterns = (cases) => testPatterns('nlToBr', cases);
  128. it('converts newlines (enabled=true)', () => {
  129. const filter = $filter('nlToBr');
  130. expect(filter('abc \n def', true)).toEqual('abc <br> def');
  131. expect(filter('a\nb\nc\\n', true)).toEqual('a<br>b<br>c\\n');
  132. });
  133. it('does not converts newlines (enabled=false)', () => {
  134. const filter = $filter('nlToBr');
  135. expect(filter('abc\ndef', false)).toEqual('abc\ndef');
  136. });
  137. it('if enabled flag is not set, converts newlines', () => {
  138. const filter = $filter('nlToBr');
  139. expect(filter('abc\ndef')).toEqual('abc<br>def');
  140. });
  141. });
  142. describe('unixToTimestring', function() {
  143. this.testPatterns = (cases) => testPatterns('unixToTimestring', cases);
  144. it('shows only time for today', () => {
  145. const d1 = new Date(); d1.setHours(8); d1.setMinutes(7);
  146. const d2 = new Date(); d2.setHours(12); d2.setMinutes(14);
  147. const d3 = new Date(); d3.setHours(0); d3.setMinutes(0);
  148. this.testPatterns([
  149. [d1.getTime() / 1000, '08:07'],
  150. [d2.getTime() / 1000, '12:14'],
  151. [d3.getTime() / 1000, '00:00'],
  152. ]);
  153. });
  154. it('shows full date with forceFull flag', () => {
  155. const d = new Date();
  156. const formatted = $filter('unixToTimestring')(d.getTime() / 1000, true);
  157. expect(formatted.length > 10).toBe(true);
  158. expect(formatted).toContain(d.getFullYear().toString());
  159. });
  160. it('shows "yesterday" for yesterday', () => {
  161. const d1 = new Date();
  162. const ts = d1.getTime();
  163. const d2 = new Date(ts - 1000 * 60 * 60 * 24);
  164. d2.setHours(8); d2.setMinutes(7);
  165. this.testPatterns([
  166. [d2.getTime() / 1000, 'date.YESTERDAY, 08:07'],
  167. ]);
  168. });
  169. it('shows full datetime for other days', () => {
  170. jasmine.clock().install();
  171. jasmine.clock().mockDate(new Date(2018, 9, 9, 20, 42));
  172. const now = new Date();
  173. const d1 = new Date(2010, 1, 7, 18, 42);
  174. const d2 = new Date(now.getFullYear(), 4, 2, 23, 59);
  175. this.testPatterns([
  176. [d1.getTime() / 1000, '7. date.month_short.FEB 2010, 18:42'],
  177. [d2.getTime() / 1000, '2. date.month_short.MAY, 23:59'],
  178. ]);
  179. });
  180. });
  181. describe('linkify', function() {
  182. let process = (text) => {
  183. return $filter('linkify')(text)
  184. };
  185. it('links http urls', () => {
  186. expect(process('hello https://threema.ch/!'))
  187. .toEqual('hello <a href="https://threema.ch/" class="autolinked autolinked-url" target="_blank" rel="noopener noreferrer">https://threema.ch/</a>!');
  188. });
  189. it('links e-mails', () => {
  190. expect(process('hello info@threema.ch!'))
  191. .toEqual('hello <a href="mailto:info@threema.ch" class="autolinked autolinked-email" target="_blank" rel="noopener noreferrer">info@threema.ch</a>!');
  192. });
  193. it('does not link phone numbers', () => {
  194. const input = 'hello +41791234567';
  195. expect(process(input)).toEqual(input);
  196. });
  197. it('does not link mentions', () => {
  198. const input = 'hello @threemaapp';
  199. expect(process(input)).toEqual(input);
  200. });
  201. it('does not link hashtags', () => {
  202. const input = 'hello #threema';
  203. expect(process(input)).toEqual(input);
  204. });
  205. });
  206. describe('displayName', function() {
  207. let process = (id) => {
  208. return $filter('displayName')(id)
  209. };
  210. it('own contact/nickname to me', () => {
  211. expect(process(webClientServiceMock.me)).toEqual('messenger.ME');
  212. });
  213. it('other contacts to displayName', () => {
  214. expect(process(webClientServiceMock.contacts.get('AAAAAAAA'))).toEqual('ContactA');
  215. expect(process(webClientServiceMock.contacts.get('XXXXXXXX'))).toEqual('ContactX');
  216. expect(process(webClientServiceMock.contacts.get('*AAAAAAA'))).toEqual('GWContactA');
  217. });
  218. });
  219. });