html_utils.js 182 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764
  1. window.onload = function() {
  2. // textCleanup
  3. QUnit.test("textCleanup", assert => {
  4. var source = "Some\nValue\n\n\nTest"
  5. var should = "Some\nValue\n\nTest"
  6. var result = App.Utils.textCleanup(source)
  7. assert.equal(result, should, source)
  8. source = "Some\nValue\n\n \n\n\nTest"
  9. should = "Some\nValue\n\nTest"
  10. result = App.Utils.textCleanup(source)
  11. assert.equal(result, should, source)
  12. source = "Some\n\rValue\n\r\n\r\n\rTest"
  13. should = "Some\nValue\n\nTest"
  14. result = App.Utils.textCleanup(source)
  15. assert.equal(result, should, source)
  16. source = "Some\n\rValue\n\r\n\r\n\rTest\r"
  17. should = "Some\nValue\n\nTest"
  18. result = App.Utils.textCleanup(source)
  19. assert.equal(result, should, source)
  20. source = "Some\r\nValue\r\n\r\n\r\nTest\r\n"
  21. should = "Some\nValue\n\nTest"
  22. result = App.Utils.textCleanup(source)
  23. assert.equal(result, should, source)
  24. source = "Some\r\nValue\r\n\r\n\r\n\r\n\r\n\r\nTest\r\n"
  25. should = "Some\nValue\n\nTest"
  26. result = App.Utils.textCleanup(source)
  27. assert.equal(result, should, source)
  28. source = "> Welcome!\n> \n> Thank you for installing Zammad.\n> \n> You will find ..."
  29. should = "> Welcome!\n>\n> Thank you for installing Zammad.\n>\n> You will find ..."
  30. result = App.Utils.textCleanup(source)
  31. assert.equal(result, should, source)
  32. });
  33. // text2html
  34. QUnit.test("text2html", assert => {
  35. var source = "Some\nValue\n\n\nTest"
  36. var should = "<div>Some</div><div>Value</div><div><br></div><div>Test</div>"
  37. var result = App.Utils.text2html(source)
  38. assert.equal(result, should, source)
  39. source = "Some\nValue\n"
  40. should = "<div>Some</div><div>Value</div>"
  41. result = App.Utils.text2html(source)
  42. assert.equal(result, should, source)
  43. source = "Some\n<b>Value</b>\n"
  44. should = "<div>Some</div><div>&lt;b&gt;Value&lt;/b&gt;</div>"
  45. result = App.Utils.text2html(source)
  46. assert.equal(result, should, source)
  47. source = "> Welcome!\n> \n> Thank you for installing Zammad.\n> \n> You will find ..."
  48. should = "<div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad.</div><div>&gt;</div><div>&gt; You will find ...</div>"
  49. result = App.Utils.text2html(source)
  50. assert.equal(result, should, source)
  51. source = "Some\nValue\n"
  52. should = "<div>Some</div><div>Value</div>"
  53. result = App.Utils.text2html(source)
  54. assert.equal(result, should, source)
  55. source = "Some\rValue\r"
  56. should = "<div>Some</div><div>Value</div>"
  57. result = App.Utils.text2html(source)
  58. assert.equal(result, should, source)
  59. source = "Some\n\rValue\n\r"
  60. should = "<div>Some</div><div>Value</div>"
  61. result = App.Utils.text2html(source)
  62. assert.equal(result, should, source)
  63. source = "Some\r\nValue\r\n"
  64. should = "<div>Some</div><div>Value</div>"
  65. result = App.Utils.text2html(source)
  66. assert.equal(result, should, source)
  67. source = "Some Value 123"
  68. should = "<span>Some &nbsp; Value 123</span>"
  69. result = App.Utils.text2html(source)
  70. assert.equal(result, should, source)
  71. source = "Some\n Value\n 123"
  72. should = "<div>Some</div><div> &nbsp; Value</div><div> &nbsp; &nbsp;123</div>"
  73. result = App.Utils.text2html(source)
  74. assert.equal(result, should, source)
  75. });
  76. // htmlStrip
  77. QUnit.test("htmlStrip", assert => {
  78. var source = $('<div><br><b>lala</b></div>')
  79. var should = '<div><b>lala</b></div>'
  80. App.Utils.htmlStrip(source)
  81. assert.equal(source.get(0).outerHTML, should)
  82. source = $('<div><br><br><br><b>lala</b></div>')
  83. should = '<div><b>lala</b></div>'
  84. App.Utils.htmlStrip(source)
  85. assert.equal(source.get(0).outerHTML, should)
  86. source = $('<div><br><br><br><b>lala</b><br><br></div>')
  87. should = '<div><b>lala</b></div>'
  88. App.Utils.htmlStrip(source)
  89. assert.equal(source.get(0).outerHTML, should)
  90. source = $('<div><br><br><div><br></div><b>lala</b><br><br></div>')
  91. should = '<div><div><br></div><b>lala</b></div>'
  92. App.Utils.htmlStrip(source)
  93. assert.equal(source.get(0).outerHTML, should)
  94. });
  95. // lastLineEmpty
  96. QUnit.test("htmlLastLineEmpty", assert => {
  97. var source = $('<div><br><b>lala</b></div>')
  98. assert.equal(App.Utils.htmlLastLineEmpty(source), false)
  99. source = $('<div><br><b>lala</b><br></div>')
  100. assert.equal(App.Utils.htmlLastLineEmpty(source), true)
  101. });
  102. // html2text
  103. QUnit.test("html2text", assert => {
  104. var source = "<div>Some</div><div>Value</div><div><br></div><div>Test</div>"
  105. var should = "Some\nValue\n\nTest"
  106. var result = App.Utils.html2text(source)
  107. assert.equal(result, should, source)
  108. source = "<div>Some</div><div>Value</div>"
  109. should = "Some\nValue"
  110. result = App.Utils.html2text(source)
  111. assert.equal(result, should, source)
  112. source = "<div>Some<br/>Value</div>"
  113. should = "Some\nValue"
  114. result = App.Utils.html2text(source)
  115. assert.equal(result, should, source)
  116. source = "<div>Some &amp; &lt;Value&gt;</div>"
  117. should = "Some & <Value>"
  118. result = App.Utils.html2text(source)
  119. assert.equal(result, should, source)
  120. source = "<div>Some</div><div>&lt;b&gt;Value&lt;/b&gt;</div>"
  121. should = "Some\n<b>Value</b>"
  122. result = App.Utils.html2text(source)
  123. assert.equal(result, should, source)
  124. source = "<div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad.</div><div>&gt;</div><div>&gt; You will find ...</div>"
  125. should = "> Welcome!\n>\n> Thank you for installing Zammad.\n>\n> You will find ..."
  126. result = App.Utils.html2text(source)
  127. assert.equal(result, should, source)
  128. source = "<div>test 123 <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>--<br/>Bob Smith</div>"
  129. should = "test 123 \n\n--\nBob Smith"
  130. result = App.Utils.html2text(source)
  131. assert.equal(result, should, source)
  132. source = "test 123 <br><br><br><br><br><br><br><br><br><br><br>--<br>Bob Smith"
  133. should = "test 123 \n\n--\nBob Smith"
  134. result = App.Utils.html2text(source)
  135. assert.equal(result, should, source)
  136. source = "<div>1<br><br><br><br><br><br><br><br><br><br></div><div>Von: Martin Edenhofer via Zammad Support [<a href=\"mailto:support@zammad.inc\" title=\"mailto:support@zammad.inc\" target=\"_blank\">mailto:support@zammad.inc</a>]</div>\n<div>Gesendet: Donnerstag, 2. April 2015 11:32</div>"
  137. should = "1\n\nVon: Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]\nGesendet: Donnerstag, 2. April 2015 11:32"
  138. result = App.Utils.html2text(source)
  139. assert.equal(result, should, source)
  140. source = "<div>test 123<br/>lalala<p>--</p>some test</div>"
  141. should = "test 123\nlalala\n--\nsome test"
  142. result = App.Utils.html2text(source)
  143. assert.equal(result, should, source)
  144. source = "<p><span>Was\nsoll verbessert werden:</span></p>"
  145. should = "Was soll verbessert werden:"
  146. result = App.Utils.html2text(source)
  147. assert.equal(result, should, source)
  148. // in raw format, without cleanup
  149. source = "<div>Some</div><div>1234</div>"
  150. should = "Some\n1234\n"
  151. result = App.Utils.html2text(source, true)
  152. assert.equal(result, should, source)
  153. source = "<div>Some</div><div> 1234</div>"
  154. should = "Some\n 1234\n"
  155. result = App.Utils.html2text(source, true)
  156. assert.equal(result, should, source)
  157. source = "\n\n<div>Some</div>\n<div> 1234</div>"
  158. should = "Some\n 1234\n"
  159. result = App.Utils.html2text(source, true)
  160. assert.equal(result, should, source)
  161. source = "<div>Some</div><div> 1234</div>"
  162. should = "Some\n 1234\n"
  163. result = App.Utils.html2text(source, true)
  164. assert.equal(result, should, source)
  165. source = "<div>Some</div>\n\n<div> 1234</div>\n"
  166. should = "Some\n 1234\n"
  167. result = App.Utils.html2text(source, true)
  168. assert.equal(result, should, source)
  169. source = "<div>test<br>new line<br></div>"
  170. should = "test\nnew line\n\n"
  171. result = App.Utils.html2text(source, true)
  172. assert.equal(result, should, source)
  173. source = "<p><span>Was\nsoll verbessert werden:</span></p>"
  174. should = "Was soll verbessert werden:\n"
  175. result = App.Utils.html2text(source, true)
  176. assert.equal(result, should, source)
  177. });
  178. // phoneify
  179. QUnit.test("phoneify", assert => {
  180. var source = "+1 123 123 123-123"
  181. var should = 'tel:+1123123123123'
  182. var result = App.Utils.phoneify(source)
  183. assert.equal(result, should, source)
  184. source = "+1 123 123 A 123-123<>"
  185. should = 'tel:+1123123123123'
  186. result = App.Utils.phoneify(source)
  187. assert.equal(result, should, source)
  188. source = "+1 (123) 123 123-123"
  189. should = 'tel:+1123123123123'
  190. result = App.Utils.phoneify(source)
  191. assert.equal(result, should, source)
  192. source = "+1 (123) 123 1#23-123"
  193. should = 'tel:+11231231#23123'
  194. result = App.Utils.phoneify(source)
  195. assert.equal(result, should, source)
  196. source = "+1 (123) 12*3 1#23-123"
  197. should = 'tel:+112312*31#23123'
  198. result = App.Utils.phoneify(source)
  199. assert.equal(result, should, source)
  200. source = "+1 (123) 12+3"
  201. should = 'tel:+1123123'
  202. result = App.Utils.phoneify(source)
  203. assert.equal(result, should, source)
  204. source = "+1 (123) 123 "
  205. should = 'tel:+1123123'
  206. result = App.Utils.phoneify(source)
  207. assert.equal(result, should, source)
  208. source = " +1 (123) 123 "
  209. should = 'tel:+1123123'
  210. result = App.Utils.phoneify(source)
  211. assert.equal(result, should, source)
  212. })
  213. // linkify
  214. QUnit.test("linkify", assert => {
  215. var source = "http://example.com"
  216. var should = '<a href="http://example.com" title="http://example.com" target="_blank">http://example.com</a>'
  217. var result = App.Utils.linkify(source)
  218. assert.equal(result, should, source)
  219. source = "http://example.com?some_param=lalala"
  220. should = '<a href="http://example.com?some_param=lalala" title="http://example.com?some_param=lalala" target="_blank">http://example.com?some_param=lalala</a>'
  221. result = App.Utils.linkify(source)
  222. assert.equal(result, should, source)
  223. source = "example.com"
  224. should = '<a href="http://example.com" title="http://example.com" target="_blank">example.com</a>'
  225. result = App.Utils.linkify(source)
  226. assert.equal(result, should, source)
  227. source = "some text example.com"
  228. should = 'some text <a href="http://example.com" title="http://example.com" target="_blank">example.com</a>'
  229. result = App.Utils.linkify(source)
  230. assert.equal(result, should, source)
  231. source = "example.com some text"
  232. should = '<a href="http://example.com" title="http://example.com" target="_blank">example.com</a> some text'
  233. result = App.Utils.linkify(source)
  234. assert.equal(result, should, source)
  235. source = "test@example.com some text"
  236. should = '<a href="mailto:test@example.com" title="mailto:test@example.com">test@example.com</a> some text'
  237. result = App.Utils.linkify(source)
  238. assert.equal(result, should, source)
  239. source = "abc domain.de-@domain.de some text"
  240. should = 'abc <a href="mailto:domain.de-@domain.de" title="mailto:domain.de-@domain.de">domain.de-@domain.de</a> some text'
  241. result = App.Utils.linkify(source)
  242. assert.equal(result, should, source)
  243. /*
  244. source = "<b>example.com</b>"
  245. should = '<b><a href="http://example.com" title="http://example.com" target="_blank">http://example.com</a></b>'
  246. result = App.Utils.linkify(source)
  247. assert.equal(result, should, source)
  248. */
  249. });
  250. // htmlEscape
  251. QUnit.test("htmlEscape", assert => {
  252. var source = "<"
  253. var should = "&lt;"
  254. var result = App.Utils.htmlEscape(source)
  255. assert.equal(result, should, source)
  256. source = ">"
  257. should = "&gt;"
  258. result = App.Utils.htmlEscape(source)
  259. assert.equal(result, should, source)
  260. source = "&"
  261. should = "&amp;"
  262. result = App.Utils.htmlEscape(source)
  263. assert.equal(result, should, source)
  264. source = "&amp;"
  265. should = "&amp;amp;"
  266. result = App.Utils.htmlEscape(source)
  267. assert.equal(result, should, source)
  268. source = "&amp ;"
  269. should = "&amp;amp ;"
  270. result = App.Utils.htmlEscape(source)
  271. assert.equal(result, should, source)
  272. source = "& amp;"
  273. should = "&amp; amp;"
  274. result = App.Utils.htmlEscape(source)
  275. assert.equal(result, should, source)
  276. source = "'test'"
  277. should = "&#39;test&#39;"
  278. result = App.Utils.htmlEscape(source)
  279. assert.equal(result, should, source)
  280. source = '"test"'
  281. should = "&quot;test&quot;"
  282. result = App.Utils.htmlEscape(source)
  283. assert.equal(result, should, source)
  284. source = "<>"
  285. should = "&lt;&gt;"
  286. result = App.Utils.htmlEscape(source)
  287. assert.equal(result, should, source)
  288. source = "<&lt;>"
  289. should = "&lt;&amp;lt;&gt;"
  290. result = App.Utils.htmlEscape(source)
  291. assert.equal(result, should, source)
  292. });
  293. // htmlRemoveTags
  294. QUnit.test("htmlRemoveTags", assert => {
  295. var source = "<div>test</div>"
  296. //var should = "<div>test</div>"
  297. var should = "test"
  298. var result = App.Utils.htmlRemoveTags($(source))
  299. assert.equal(result.html(), should, source)
  300. source = "<div>test<!-- some comment --></div>"
  301. //should = "<div>test</div>"
  302. should = "test"
  303. result = App.Utils.htmlRemoveTags($(source))
  304. assert.equal(result.html(), should, source)
  305. source = "<a href=\"some_link\">some link to somewhere</a>"
  306. should = "some link to somewhere"
  307. result = App.Utils.htmlRemoveTags($(source))
  308. assert.equal(result.html(), should, source)
  309. source = "<div><a href=\"some_link\">some link to somewhere</a></div>"
  310. //should = "<div>some link to somewhere</div>"
  311. should = "some link to somewhere"
  312. result = App.Utils.htmlRemoveTags($(source))
  313. assert.equal(result.html(), should, source)
  314. source = "<div><a href=\"some_link\">some link to somewhere</a><input value=\"should not be shown\"></div>"
  315. //should = "<div>some link to somewhere</div>"
  316. should = "some link to somewhere"
  317. result = App.Utils.htmlRemoveTags($(source))
  318. assert.equal(result.html(), should, source)
  319. source = "<div><a href=\"some_link\">some link to somewhere</a> <div><hr></div> <span>123</span> <img src=\"some_image\"/></div>"
  320. //should = "<div>some link to somewhere 123 </div>"
  321. should = "some link to somewhere 123 "
  322. result = App.Utils.htmlRemoveTags($(source))
  323. assert.equal(result.html(), should, source)
  324. });
  325. // htmlRemoveRichtext
  326. QUnit.test("htmlRemoveRichtext", assert => {
  327. source = "<div><form class=\"xxx\">test 123</form><svg><use xlink:href=\"" + App.Config.get('icons_url') + "#icon-status\"></svg></div>"
  328. //should = "<div>test 123</div>"
  329. should = "test 123"
  330. result = App.Utils.htmlRemoveRichtext($(source))
  331. assert.equal(result.html(), should, source)
  332. source = "<div><textarea class=\"xxx\">test 123</textarea></div>"
  333. //should = "<div>test 123</div>"
  334. should = "test 123"
  335. result = App.Utils.htmlRemoveRichtext($(source))
  336. assert.equal(result.html(), should, source)
  337. source = "<div><p wrap=\"\">test 123</p></div>"
  338. should = "<p>test 123</p>"
  339. result = App.Utils.htmlRemoveRichtext($(source))
  340. assert.equal(result.html(), should, source)
  341. source = "<div><font size=\"3\" color=\"red\">This is some text!</font></div>"
  342. should = "This is some text!"
  343. result = App.Utils.htmlRemoveRichtext($(source))
  344. assert.equal(result.html(), should, source)
  345. should = "This is some text!"
  346. result = App.Utils.htmlRemoveRichtext(source)
  347. assert.equal(result.html(), should, source)
  348. var source = "<div><!--test comment--><a href=\"test\">test</a></div>"
  349. //var should = "<div>test</div>"
  350. var should = "test"
  351. var result = App.Utils.htmlRemoveRichtext($(source))
  352. assert.equal(result.html(), should, source)
  353. source = "<div><!--[if !supportLists]--><span lang=\"DE\">1.1.1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><!--[endif]--><span lang=\"DE\">Description</span></div>"
  354. //should = "<div><span>1.1.1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span>Description</span></div>"
  355. should = "<span>1.1.1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span>Description</span>"
  356. //should = '1.1.1 Description'
  357. result = App.Utils.htmlRemoveRichtext($(source))
  358. assert.equal(result.html(), should, source)
  359. source = "<a href=\"some_link\">some link to somewhere</a>"
  360. should = "some link to somewhere"
  361. result = App.Utils.htmlRemoveRichtext($(source))
  362. assert.equal(result.html(), should, source)
  363. source = "<div><a href=\"some_link\"></a> test </div>"
  364. //should = "<div> test </div>"
  365. should = " test "
  366. result = App.Utils.htmlRemoveRichtext($(source))
  367. assert.equal(result.html(), should, source)
  368. source = "<div><b></b> test </div>"
  369. //should = "<div> test </div>"
  370. should = " test "
  371. result = App.Utils.htmlRemoveRichtext($(source))
  372. assert.equal(result.html(), should, source)
  373. source = "<div><div><b></b> test </div></div>"
  374. //should = "<div><div> test </div></div>"
  375. should = "<div> test </div>"
  376. result = App.Utils.htmlRemoveRichtext($(source))
  377. assert.equal(result.html(), should, source)
  378. source = "<div><div><b></b> test <input value=\"should not be shown\"></div></div>"
  379. //should = "<div><div> test </div></div>"
  380. should = "<div> test </div>"
  381. result = App.Utils.htmlRemoveRichtext($(source))
  382. assert.equal(result.html(), should, source)
  383. source = "<div><div><b></b> test </div><span>123</span></div>"
  384. //should = "<div><div> test </div><span>123</span></div>"
  385. should = "<div> test </div><span>123</span>"
  386. //should = '<div> test </div>123'
  387. result = App.Utils.htmlRemoveRichtext($(source))
  388. assert.equal(result.html(), should, source)
  389. source = "<div><div class=\"xxx\" title=\"some title\" lang=\"en\"><b></b> test </div></div>"
  390. //should = "<div><div> test </div></div>"
  391. should = "<div> test </div>"
  392. result = App.Utils.htmlRemoveRichtext($(source))
  393. assert.equal(result.html(), should, source)
  394. source = "<div><textarea class=\"xxx\"> test </textarea></div>"
  395. //should = "<div> test </div>"
  396. should = " test "
  397. result = App.Utils.htmlRemoveRichtext($(source))
  398. assert.equal(result.html(), should, source)
  399. source = "<div><br></div>"
  400. //should = "<div><br></div>"
  401. should = "<br>"
  402. result = App.Utils.htmlRemoveRichtext($(source))
  403. assert.equal(result.html(), should, source)
  404. source = "<div><div class=\"xxx\"><br></div></div>"
  405. //should = "<div><div><br></div></div>"
  406. should = "<div><br></div>"
  407. result = App.Utils.htmlRemoveRichtext($(source))
  408. assert.equal(result.html(), should, source)
  409. source = "<div><form class=\"xxx\">test 123</form></div>"
  410. //should = "<div>test 123</div>"
  411. should = "test 123"
  412. result = App.Utils.htmlRemoveRichtext($(source))
  413. assert.equal(result.html(), should, source)
  414. source = "<div><div><label for=\"Ticket_888344_group_id\">Gruppe <span>*</span></label></div><div><div></div></div><div><div><span></span><span></span></div></div><div><div><label for=\"Ticket_888344_owner_id\">Besitzer <span></span></label></div><div><div></div></div></div><div><div><div><svg><use xlink:href=\"http://localhost:3000/" + App.Config.get('icons_url') + "#icon-arrow-down\"></use></svg></div><span></span><span></span></div></div><div><div> <label for=\"Ticket_888344_state_id\">Status <span>*</span></label></div></div></div>\n"
  415. //should = "<div>test 123</div>"
  416. should = '<div>Gruppe <span>*</span></div><div><div></div></div><div><div><span></span><span></span></div></div><div><div>Besitzer <span></span></div><div><div></div></div></div><div><div><div></div><span></span><span></span></div></div><div><div> Status <span>*</span></div></div>'
  417. result = App.Utils.htmlRemoveRichtext(source)
  418. assert.equal(result.html(), should, source)
  419. source = "<div><font size=\"3\" color=\"red\">This is some text!</font><svg><use xlink:href=\"" + App.Config.get('icons_url') + "#icon-status\"></svg></div>"
  420. should = "This is some text!"
  421. result = App.Utils.htmlRemoveRichtext($(source))
  422. assert.equal(result.html(), should, source)
  423. should = "This is some text!"
  424. result = App.Utils.htmlRemoveRichtext(source)
  425. assert.equal(result.html(), should, source)
  426. var source = "<div><!--test comment--><a href=\"test\">test</a></div>"
  427. var should = "<div>test</div>"
  428. var result = App.Utils.htmlRemoveRichtext($(source))
  429. assert.equal(result.get(0).outerHTML, should, source)
  430. source = "<div><small>some link to somewhere</small></a>"
  431. should = "<div>some link to somewhere</div>"
  432. result = App.Utils.htmlRemoveRichtext($(source))
  433. assert.equal(result.get(0).outerHTML, should, source)
  434. source = "<div><div class=\"xxx\"><br></div></div>"
  435. should = "<div><div><br></div></div>"
  436. result = App.Utils.htmlRemoveRichtext($(source))
  437. assert.equal(result.get(0).outerHTML, should, source)
  438. source = "<div><table bgcolor=\"green\" aaa=\"1\"><thead><tr><th>111</th><th colspan=\"2\" abc=\"a\">aaa</th></tr></thead><tbody><tr><td>key</td><td>value</td></tr></tbody></table></div>"
  439. should = "<div>111aaakeyvalue</div>"
  440. result = App.Utils.htmlRemoveRichtext(source, true)
  441. assert.equal(result.get(0).outerHTML, should, source)
  442. });
  443. // htmlCleanup
  444. QUnit.test("htmlCleanup", assert => {
  445. var source = "<div><!--test comment--><a href=\"test\">test</a></div>"
  446. //var should = "<div>test</div>"
  447. var should = "<a href=\"test\">test</a>"
  448. var result = App.Utils.htmlCleanup($(source))
  449. assert.equal(result.html(), should, source)
  450. source = "<div><!--test comment--><a href=\"test\">test</a></div>"
  451. should = "<a href=\"test\">test</a>"
  452. result = App.Utils.htmlCleanup(source)
  453. assert.equal(result.html(), should, source)
  454. source = "some link to somewhere"
  455. should = "some link to somewhere"
  456. result = App.Utils.htmlCleanup(source)
  457. assert.equal(result.html(), should, source)
  458. source = "<li>a</li><li>b</li>"
  459. should = "<li>a</li><li>b</li>"
  460. result = App.Utils.htmlCleanup(source)
  461. assert.equal(result.html(), should, source)
  462. source = "<a href=\"some_link\">some link to somewhere</a>"
  463. should = "some link to somewhere"
  464. result = App.Utils.htmlCleanup($(source))
  465. assert.equal(result.html(), should, source)
  466. source = "<p><a href=\"some_link\">some link to somewhere</a><p>"
  467. should = "<a href=\"some_link\">some link to somewhere</a>"
  468. result = App.Utils.htmlCleanup($(source))
  469. assert.equal(result.html(), should, source)
  470. source = "<div><h1>some link to somewhere</h1></div>"
  471. should = "<h1>some link to somewhere</h1>"
  472. result = App.Utils.htmlCleanup($(source))
  473. assert.equal(result.html(), should, source)
  474. source = "<div><p id=\"123\" data-id=\"abc\">some link to somewhere</p></div>"
  475. should = "<p>some link to somewhere</p>"
  476. result = App.Utils.htmlCleanup($(source))
  477. assert.equal(result.html(), should, source)
  478. source = "<div><small>some link to somewhere</small></a>"
  479. //should = "<div>some link to somewhere</div>"
  480. should = "some link to somewhere"
  481. result = App.Utils.htmlCleanup($(source))
  482. assert.equal(result.html(), should, source)
  483. source = "<div><time>some link to somewhere</time></a>"
  484. //should = "<div>some link to somewhere</div>"
  485. should = "some link to somewhere"
  486. result = App.Utils.htmlCleanup($(source))
  487. assert.equal(result.html(), should, source)
  488. source = "<div><h1>some h1 for somewhere</h1><p><hr></p></div>"
  489. should = "<h1>some h1 for somewhere</h1><p></p><hr><p></p>"
  490. result = App.Utils.htmlCleanup($(source))
  491. assert.equal(result.html(), should, source)
  492. source = "<div><br></div>"
  493. //should = "<div><br></div>"
  494. should = "<br>"
  495. result = App.Utils.htmlCleanup($(source))
  496. assert.equal(result.html(), should, source)
  497. source = "<div><div class=\"xxx\"><br></div></div>"
  498. //should = "<div><div><br></div></div>"
  499. should = "<div><br></div>"
  500. result = App.Utils.htmlCleanup($(source))
  501. assert.equal(result.html(), should, source)
  502. source = "<div><form class=\"xxx\">test 123</form></div>"
  503. //should = "<div>test 123<br></div>"
  504. should = "test 123"
  505. result = App.Utils.htmlCleanup($(source))
  506. assert.equal(result.html(), should, source)
  507. source = "<div><form class=\"xxx\">test 123</form> some other value</div>"
  508. //should = "<div>test 123 some other value</div>"
  509. should = "test 123 some other value"
  510. result = App.Utils.htmlCleanup($(source))
  511. assert.equal(result.html(), should, source)
  512. source = "<div><form class=\"xxx\">test 123</form> some other value<input value=\"should not be shown\"></div>"
  513. //should = "<div>test 123 some other value</div>"
  514. should = "test 123 some other value"
  515. result = App.Utils.htmlCleanup($(source))
  516. assert.equal(result.html(), should, source)
  517. source = "<div><font size=\"3\" color=\"red\">This is some text!</font><svg><use xlink:href=\"" + App.Config.get('icons_url') + "#icon-status\"></svg></div>"
  518. //should = "<div>This is some text!</div>"
  519. should = "<font color=\"red\">This is some text!</font>"
  520. result = App.Utils.htmlCleanup($(source))
  521. assert.equal(result.html(), should, source)
  522. source = "<div><p>some link to somewhere from word<w:sdt>abc</w:sdt></p><o:p></o:p></a>"
  523. //should = "<div><p>some link to somewhere from wordabc</p></div>"
  524. should = '<p>some link to somewhere from wordabc</p>'
  525. result = App.Utils.htmlCleanup($(source))
  526. assert.equal(result.html(), should, source)
  527. source = "<div><div><label for=\"Ticket_888344_group_id\">Gruppe <span>*</span></label></div><div><div></div></div><div><div><span></span><span></span></div></div><div><div><label for=\"Ticket_888344_owner_id\">Besitzer <span></span></label></div><div><div></div></div></div><div><div><div><svg><use xlink:href=\"http://localhost:3000/" + App.Config.get('icons_url') + "#icon-arrow-down\"></use></svg></div><span></span><span></span></div></div><div><div> <label for=\"Ticket_888344_state_id\">Status <span>*</span></label></div></div></div>\n"
  528. //should = "<div>test 123</div>"
  529. should = '<div>Gruppe <span>*</span></div><div><div></div></div><div><div><span></span><span></span></div></div><div><div>Besitzer <span></span></div><div><div></div></div></div><div><div><div></div><span></span><span></span></div></div><div><div> Status <span>*</span></div></div>'
  530. result = App.Utils.htmlCleanup(source)
  531. assert.equal(result.html(), should, source)
  532. source = "<html xmlns:o=\"urn:schemas-microsoft-com:office:office\"\nxmlns:w=\"urn:schemas-microsoft-com:office:word\"\nxmlns:m=\"http://schemas.microsoft.com/office/2004/12/omml\"\nxmlns=\"http://www.w3.org/TR/REC-html40\">\n\n<head>\n<meta name=Titel content=\"\">\n<meta name=Stichwörter content=\"\">\n<meta http-equiv=Content-Type content=\"text/html; charset=utf-8\">\n<meta name=ProgId content=Word.Document>\n<meta name=Generator content=\"Microsoft Word 15\">\n<meta name=Originator content=\"Microsoft Word 15\">\n<link rel=File-List\nhref=\"file://localhost/Users/johannes/Library/Group%20Containers/UBF8T346G9.Office/msoclip1/01/clip_filelist.xml\">\n<!--[if gte mso 9]><xml>\n <o:OfficeDocumentSettings>\n <o:AllowPNG/>\n <o:PixelsPerInch>96</o:PixelsPerInch>\n </o:OfficeDocumentSettings>\n</xml><![endif]-->\n<link rel=themeData\nhref=\"file://localhost/Users/johannes/Library/Group%20Containers/UBF8T346G9.Office/msoclip1/01/clip_themedata.thmx\">\n<!--[if gte mso 9]><xml>\n <w:WordDocument>\n <w:View>Normal</w:View>\n <w:Zoom>0</w:Zoom>\n <w:TrackMoves/>\n <w:TrackFormatting/>\n <w:HyphenationZone>21</w:HyphenationZone>\n <w:PunctuationKerning/>\n <w:ValidateAgainstSchemas/>\n <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>\n <w:IgnoreMixedContent>false</w:IgnoreMixedContent>\n <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>\n <w:DoNotPromoteQF/>\n <w:LidThemeOther>DE</w:LidThemeOther>\n <w:LidThemeAsian>X-NONE</w:LidThemeAsian>\n <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>\n <w:Compatibility>\n <w:BreakWrappedTables/>\n <w:SnapToGridInCell/>\n <w:WrapTextWithPunct/>\n <w:UseAsianBreakRules/>\n <w:DontGrowAutofit/>\n <w:SplitPgBreakAndParaMark/>\n <w:EnableOpenTypeKerning/>\n <w:DontFlipMirrorIndents/>\n <w:OverrideTableStyleHps/>\n </w:Compatibility>\n <m:mathPr>\n <m:mathFont m:val=\"Cambria Math\"/>\n <m:brkBin m:val=\"before\"/>\n <m:brkBinSub m:val=\"&#45;-\"/>\n <m:smallFrac m:val=\"off\"/>\n <m:dispDef/>\n <m:lMargin m:val=\"0\"/>\n <m:rMargin m:val=\"0\"/>\n <m:defJc m:val=\"centerGroup\"/>\n <m:wrapIndent m:val=\"1440\"/>\n <m:intLim m:val=\"subSup\"/>\n <m:naryLim m:val=\"undOvr\"/>\n </m:mathPr></w:WordDocument>\n</xml><![endif]--><!--[if gte mso 9]><xml>\n <w:LatentStyles DefLockedState=\"false\" DefUnhideWhenUsed=\"false\"\n DefSemiHidden=\"false\" DefQFormat=\"false\" DefPriority=\"99\"\n LatentStyleCount=\"380\">\n <w:LsdException Locked=\"false\" Priority=\"0\" QFormat=\"true\" Name=\"Normal\"/>\n <w:LsdException Locked=\"false\" Priority=\"0\" QFormat=\"true\" Name=\"heading 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"0\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"heading 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"0\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"heading 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"0\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"heading 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"0\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"heading 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"9\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"heading 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"9\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"heading 7\"/>\n <w:LsdException Locked=\"false\" Priority=\"9\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"heading 8\"/>\n <w:LsdException Locked=\"false\" Priority=\"9\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"heading 9\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index 5\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index 6\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index 7\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index 8\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index 9\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"toc 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"toc 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"toc 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"toc 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"toc 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"toc 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"toc 7\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"toc 8\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"toc 9\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Normal Indent\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"footnote text\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"annotation text\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"header\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"footer\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"index heading\"/>\n <w:LsdException Locked=\"false\" Priority=\"35\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"caption\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"table of figures\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"envelope address\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"envelope return\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"footnote reference\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"annotation reference\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"line number\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"page number\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"endnote reference\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"endnote text\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"table of authorities\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"macro\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"toa heading\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Bullet\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Number\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List 5\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Bullet 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Bullet 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Bullet 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Bullet 5\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Number 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Number 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Number 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Number 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"10\" QFormat=\"true\" Name=\"Title\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Closing\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Signature\"/>\n <w:LsdException Locked=\"false\" Priority=\"1\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"Default Paragraph Font\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Body Text\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Body Text Indent\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Continue\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Continue 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Continue 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Continue 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"List Continue 5\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Message Header\"/>\n <w:LsdException Locked=\"false\" Priority=\"11\" QFormat=\"true\" Name=\"Subtitle\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Salutation\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Date\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Body Text First Indent\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Body Text First Indent 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Heading\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Body Text 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Body Text 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Body Text Indent 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Body Text Indent 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Block Text\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Hyperlink\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"FollowedHyperlink\"/>\n <w:LsdException Locked=\"false\" Priority=\"22\" QFormat=\"true\" Name=\"Strong\"/>\n <w:LsdException Locked=\"false\" Priority=\"20\" QFormat=\"true\" Name=\"Emphasis\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Document Map\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Plain Text\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"E-mail Signature\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Top of Form\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Bottom of Form\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Normal (Web)\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Acronym\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Address\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Cite\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Code\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Definition\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Keyboard\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Preformatted\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Sample\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Typewriter\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"HTML Variable\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Normal Table\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"annotation subject\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"No List\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Outline List 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Outline List 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Outline List 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Simple 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Simple 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Simple 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Classic 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Classic 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Classic 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Classic 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Colorful 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Colorful 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Colorful 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Columns 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Columns 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Columns 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Columns 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Columns 5\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Grid 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Grid 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Grid 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Grid 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Grid 5\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Grid 6\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Grid 7\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Grid 8\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table List 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table List 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table List 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table List 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table List 5\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table List 6\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table List 7\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table List 8\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table 3D effects 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table 3D effects 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table 3D effects 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Contemporary\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Elegant\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Professional\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Subtle 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Subtle 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Web 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Web 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Web 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Balloon Text\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" Name=\"Table Grid\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Table Theme\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Level 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Level 2\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Level 3\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Level 4\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Level 5\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Level 6\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Level 7\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Level 8\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" UnhideWhenUsed=\"true\"\n Name=\"Note Level 9\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" Name=\"Placeholder Text\"/>\n <w:LsdException Locked=\"false\" Priority=\"1\" QFormat=\"true\" Name=\"No Spacing\"/>\n <w:LsdException Locked=\"false\" Priority=\"60\" Name=\"Light Shading\"/>\n <w:LsdException Locked=\"false\" Priority=\"61\" Name=\"Light List\"/>\n <w:LsdException Locked=\"false\" Priority=\"62\" Name=\"Light Grid\"/>\n <w:LsdException Locked=\"false\" Priority=\"63\" Name=\"Medium Shading 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"64\" Name=\"Medium Shading 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"65\" Name=\"Medium List 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"66\" Name=\"Medium List 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"67\" Name=\"Medium Grid 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"68\" Name=\"Medium Grid 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"69\" Name=\"Medium Grid 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"70\" Name=\"Dark List\"/>\n <w:LsdException Locked=\"false\" Priority=\"71\" Name=\"Colorful Shading\"/>\n <w:LsdException Locked=\"false\" Priority=\"72\" Name=\"Colorful List\"/>\n <w:LsdException Locked=\"false\" Priority=\"73\" Name=\"Colorful Grid\"/>\n <w:LsdException Locked=\"false\" Priority=\"60\" Name=\"Light Shading Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"61\" Name=\"Light List Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"62\" Name=\"Light Grid Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"63\" Name=\"Medium Shading 1 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"64\" Name=\"Medium Shading 2 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"65\" Name=\"Medium List 1 Accent 1\"/>\n <w:LsdException Locked=\"false\" SemiHidden=\"true\" Name=\"Revision\"/>\n <w:LsdException Locked=\"false\" Priority=\"34\" QFormat=\"true\"\n Name=\"List Paragraph\"/>\n <w:LsdException Locked=\"false\" Priority=\"29\" QFormat=\"true\" Name=\"Quote\"/>\n <w:LsdException Locked=\"false\" Priority=\"30\" QFormat=\"true\"\n Name=\"Intense Quote\"/>\n <w:LsdException Locked=\"false\" Priority=\"66\" Name=\"Medium List 2 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"67\" Name=\"Medium Grid 1 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"68\" Name=\"Medium Grid 2 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"69\" Name=\"Medium Grid 3 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"70\" Name=\"Dark List Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"71\" Name=\"Colorful Shading Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"72\" Name=\"Colorful List Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"73\" Name=\"Colorful Grid Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"60\" Name=\"Light Shading Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"61\" Name=\"Light List Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"62\" Name=\"Light Grid Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"63\" Name=\"Medium Shading 1 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"64\" Name=\"Medium Shading 2 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"65\" Name=\"Medium List 1 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"66\" Name=\"Medium List 2 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"67\" Name=\"Medium Grid 1 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"68\" Name=\"Medium Grid 2 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"69\" Name=\"Medium Grid 3 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"70\" Name=\"Dark List Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"71\" Name=\"Colorful Shading Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"72\" Name=\"Colorful List Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"73\" Name=\"Colorful Grid Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"60\" Name=\"Light Shading Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"61\" Name=\"Light List Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"62\" Name=\"Light Grid Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"63\" Name=\"Medium Shading 1 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"64\" Name=\"Medium Shading 2 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"65\" Name=\"Medium List 1 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"66\" Name=\"Medium List 2 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"67\" Name=\"Medium Grid 1 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"68\" Name=\"Medium Grid 2 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"69\" Name=\"Medium Grid 3 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"70\" Name=\"Dark List Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"71\" Name=\"Colorful Shading Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"72\" Name=\"Colorful List Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"73\" Name=\"Colorful Grid Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"60\" Name=\"Light Shading Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"61\" Name=\"Light List Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"62\" Name=\"Light Grid Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"63\" Name=\"Medium Shading 1 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"64\" Name=\"Medium Shading 2 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"65\" Name=\"Medium List 1 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"66\" Name=\"Medium List 2 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"67\" Name=\"Medium Grid 1 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"68\" Name=\"Medium Grid 2 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"69\" Name=\"Medium Grid 3 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"70\" Name=\"Dark List Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"71\" Name=\"Colorful Shading Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"72\" Name=\"Colorful List Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"73\" Name=\"Colorful Grid Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"60\" Name=\"Light Shading Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"61\" Name=\"Light List Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"62\" Name=\"Light Grid Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"63\" Name=\"Medium Shading 1 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"64\" Name=\"Medium Shading 2 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"65\" Name=\"Medium List 1 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"66\" Name=\"Medium List 2 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"67\" Name=\"Medium Grid 1 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"68\" Name=\"Medium Grid 2 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"69\" Name=\"Medium Grid 3 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"70\" Name=\"Dark List Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"71\" Name=\"Colorful Shading Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"72\" Name=\"Colorful List Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"73\" Name=\"Colorful Grid Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"60\" Name=\"Light Shading Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"61\" Name=\"Light List Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"62\" Name=\"Light Grid Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"63\" Name=\"Medium Shading 1 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"64\" Name=\"Medium Shading 2 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"65\" Name=\"Medium List 1 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"66\" Name=\"Medium List 2 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"67\" Name=\"Medium Grid 1 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"68\" Name=\"Medium Grid 2 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"69\" Name=\"Medium Grid 3 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"70\" Name=\"Dark List Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"71\" Name=\"Colorful Shading Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"72\" Name=\"Colorful List Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"73\" Name=\"Colorful Grid Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"19\" QFormat=\"true\"\n Name=\"Subtle Emphasis\"/>\n <w:LsdException Locked=\"false\" Priority=\"21\" QFormat=\"true\"\n Name=\"Intense Emphasis\"/>\n <w:LsdException Locked=\"false\" Priority=\"31\" QFormat=\"true\"\n Name=\"Subtle Reference\"/>\n <w:LsdException Locked=\"false\" Priority=\"32\" QFormat=\"true\"\n Name=\"Intense Reference\"/>\n <w:LsdException Locked=\"false\" Priority=\"33\" QFormat=\"true\" Name=\"Book Title\"/>\n <w:LsdException Locked=\"false\" Priority=\"37\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" Name=\"Bibliography\"/>\n <w:LsdException Locked=\"false\" Priority=\"39\" SemiHidden=\"true\"\n UnhideWhenUsed=\"true\" QFormat=\"true\" Name=\"TOC Heading\"/>\n <w:LsdException Locked=\"false\" Priority=\"41\" Name=\"Plain Table 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"42\" Name=\"Plain Table 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"43\" Name=\"Plain Table 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"44\" Name=\"Plain Table 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"45\" Name=\"Plain Table 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"40\" Name=\"Grid Table Light\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\" Name=\"Grid Table 1 Light\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"Grid Table 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"Grid Table 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"Grid Table 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"Grid Table 5 Dark\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\" Name=\"Grid Table 6 Colorful\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\" Name=\"Grid Table 7 Colorful\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"Grid Table 1 Light Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"Grid Table 2 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"Grid Table 3 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"Grid Table 4 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"Grid Table 5 Dark Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"Grid Table 6 Colorful Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"Grid Table 7 Colorful Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"Grid Table 1 Light Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"Grid Table 2 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"Grid Table 3 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"Grid Table 4 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"Grid Table 5 Dark Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"Grid Table 6 Colorful Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"Grid Table 7 Colorful Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"Grid Table 1 Light Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"Grid Table 2 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"Grid Table 3 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"Grid Table 4 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"Grid Table 5 Dark Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"Grid Table 6 Colorful Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"Grid Table 7 Colorful Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"Grid Table 1 Light Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"Grid Table 2 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"Grid Table 3 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"Grid Table 4 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"Grid Table 5 Dark Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"Grid Table 6 Colorful Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"Grid Table 7 Colorful Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"Grid Table 1 Light Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"Grid Table 2 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"Grid Table 3 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"Grid Table 4 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"Grid Table 5 Dark Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"Grid Table 6 Colorful Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"Grid Table 7 Colorful Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"Grid Table 1 Light Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"Grid Table 2 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"Grid Table 3 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"Grid Table 4 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"Grid Table 5 Dark Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"Grid Table 6 Colorful Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"Grid Table 7 Colorful Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\" Name=\"List Table 1 Light\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"List Table 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"List Table 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"List Table 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"List Table 5 Dark\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\" Name=\"List Table 6 Colorful\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\" Name=\"List Table 7 Colorful\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"List Table 1 Light Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"List Table 2 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"List Table 3 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"List Table 4 Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"List Table 5 Dark Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"List Table 6 Colorful Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"List Table 7 Colorful Accent 1\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"List Table 1 Light Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"List Table 2 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"List Table 3 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"List Table 4 Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"List Table 5 Dark Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"List Table 6 Colorful Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"List Table 7 Colorful Accent 2\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"List Table 1 Light Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"List Table 2 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"List Table 3 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"List Table 4 Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"List Table 5 Dark Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"List Table 6 Colorful Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"List Table 7 Colorful Accent 3\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"List Table 1 Light Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"List Table 2 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"List Table 3 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"List Table 4 Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"List Table 5 Dark Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"List Table 6 Colorful Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"List Table 7 Colorful Accent 4\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"List Table 1 Light Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"List Table 2 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"List Table 3 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"List Table 4 Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"List Table 5 Dark Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"List Table 6 Colorful Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"List Table 7 Colorful Accent 5\"/>\n <w:LsdException Locked=\"false\" Priority=\"46\"\n Name=\"List Table 1 Light Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"47\" Name=\"List Table 2 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"48\" Name=\"List Table 3 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"49\" Name=\"List Table 4 Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"50\" Name=\"List Table 5 Dark Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"51\"\n Name=\"List Table 6 Colorful Accent 6\"/>\n <w:LsdException Locked=\"false\" Priority=\"52\"\n Name=\"List Table 7 Colorful Accent 6\"/>\n </w:LatentStyles>\n</xml><![endif]-->\n<style>\n<!--\n /* Font Definitions */\n@font-face\n {font-family:\"Courier New\";\n panose-1:2 7 3 9 2 2 5 2 4 4;\n mso-font-charset:0;\n mso-generic-font-family:auto;\n mso-font-pitch:variable;\n mso-font-signature:-536859905 -1073711037 9 0 511 0;}\n@font-face\n {font-family:Wingdings;\n panose-1:5 0 0 0 0 0 0 0 0 0;\n mso-font-charset:2;\n mso-generic-font-family:auto;\n mso-font-pitch:variable;\n mso-font-signature:0 268435456 0 0 -2147483648 0;}\n@font-face\n {font-family:\"Cambria Math\";\n panose-1:2 4 5 3 5 4 6 3 2 4;\n mso-font-charset:0;\n mso-generic-font-family:auto;\n mso-font-pitch:variable;\n mso-font-signature:-536870145 1107305727 0 0 415 0;}\n@font-face\n {font-family:Calibri;\n panose-1:2 15 5 2 2 2 4 3 2 4;\n mso-font-charset:0;\n mso-generic-font-family:auto;\n mso-font-pitch:variable;\n mso-font-signature:-536870145 1073786111 1 0 415 0;}\n /* Style Definitions */\np.MsoNormal, li.MsoNormal, div.MsoNormal\n {mso-style-unhide:no;\n mso-style-qformat:yes;\n mso-style-parent:\"\";\n margin:0cm;\n margin-bottom:.0001pt;\n mso-pagination:widow-orphan;\n font-size:12.0pt;\n font-family:Calibri;\n mso-ascii-font-family:Calibri;\n mso-ascii-theme-font:minor-latin;\n mso-fareast-font-family:Calibri;\n mso-fareast-theme-font:minor-latin;\n mso-hansi-font-family:Calibri;\n mso-hansi-theme-font:minor-latin;\n mso-bidi-font-family:\"Times New Roman\";\n mso-bidi-theme-font:minor-bidi;\n mso-fareast-language:EN-US;}\np.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph\n {mso-style-priority:34;\n mso-style-unhide:no;\n mso-style-qformat:yes;\n margin-top:0cm;\n margin-right:0cm;\n margin-bottom:0cm;\n margin-left:36.0pt;\n margin-bottom:.0001pt;\n mso-add-space:auto;\n mso-pagination:widow-orphan;\n font-size:12.0pt;\n font-family:Calibri;\n mso-ascii-font-family:Calibri;\n mso-ascii-theme-font:minor-latin;\n mso-fareast-font-family:Calibri;\n mso-fareast-theme-font:minor-latin;\n mso-hansi-font-family:Calibri;\n mso-hansi-theme-font:minor-latin;\n mso-bidi-font-family:\"Times New Roman\";\n mso-bidi-theme-font:minor-bidi;\n mso-fareast-language:EN-US;}\np.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst\n {mso-style-priority:34;\n mso-style-unhide:no;\n mso-style-qformat:yes;\n mso-style-type:export-only;\n margin-top:0cm;\n margin-right:0cm;\n margin-bottom:0cm;\n margin-left:36.0pt;\n margin-bottom:.0001pt;\n mso-add-space:auto;\n mso-pagination:widow-orphan;\n font-size:12.0pt;\n font-family:Calibri;\n mso-ascii-font-family:Calibri;\n mso-ascii-theme-font:minor-latin;\n mso-fareast-font-family:Calibri;\n mso-fareast-theme-font:minor-latin;\n mso-hansi-font-family:Calibri;\n mso-hansi-theme-font:minor-latin;\n mso-bidi-font-family:\"Times New Roman\";\n mso-bidi-theme-font:minor-bidi;\n mso-fareast-language:EN-US;}\np.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle\n {mso-style-priority:34;\n mso-style-unhide:no;\n mso-style-qformat:yes;\n mso-style-type:export-only;\n margin-top:0cm;\n margin-right:0cm;\n margin-bottom:0cm;\n margin-left:36.0pt;\n margin-bottom:.0001pt;\n mso-add-space:auto;\n mso-pagination:widow-orphan;\n font-size:12.0pt;\n font-family:Calibri;\n mso-ascii-font-family:Calibri;\n mso-ascii-theme-font:minor-latin;\n mso-fareast-font-family:Calibri;\n mso-fareast-theme-font:minor-latin;\n mso-hansi-font-family:Calibri;\n mso-hansi-theme-font:minor-latin;\n mso-bidi-font-family:\"Times New Roman\";\n mso-bidi-theme-font:minor-bidi;\n mso-fareast-language:EN-US;}\np.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast\n {mso-style-priority:34;\n mso-style-unhide:no;\n mso-style-qformat:yes;\n mso-style-type:export-only;\n margin-top:0cm;\n margin-right:0cm;\n margin-bottom:0cm;\n margin-left:36.0pt;\n margin-bottom:.0001pt;\n mso-add-space:auto;\n mso-pagination:widow-orphan;\n font-size:12.0pt;\n font-family:Calibri;\n mso-ascii-font-family:Calibri;\n mso-ascii-theme-font:minor-latin;\n mso-fareast-font-family:Calibri;\n mso-fareast-theme-font:minor-latin;\n mso-hansi-font-family:Calibri;\n mso-hansi-theme-font:minor-latin;\n mso-bidi-font-family:\"Times New Roman\";\n mso-bidi-theme-font:minor-bidi;\n mso-fareast-language:EN-US;}\n.MsoChpDefault\n {mso-style-type:export-only;\n mso-default-props:yes;\n font-family:Calibri;\n mso-ascii-font-family:Calibri;\n mso-ascii-theme-font:minor-latin;\n mso-fareast-font-family:Calibri;\n mso-fareast-theme-font:minor-latin;\n mso-hansi-font-family:Calibri;\n mso-hansi-theme-font:minor-latin;\n mso-bidi-font-family:\"Times New Roman\";\n mso-bidi-theme-font:minor-bidi;\n mso-fareast-language:EN-US;}\n@page WordSection1\n {size:595.0pt 842.0pt;\n margin:70.85pt 70.85pt 2.0cm 70.85pt;\n mso-header-margin:35.4pt;\n mso-footer-margin:35.4pt;\n mso-paper-source:0;}\ndiv.WordSection1\n {page:WordSection1;}\n /* List Definitions */\n@list l0\n {mso-list-id:240799396;\n mso-list-type:hybrid;\n mso-list-template-ids:1377200210 67567617 67567619 67567621 67567617 67567619 67567621 67567617 67567619 67567621;}\n@list l0:level1\n {mso-level-number-format:bullet;\n mso-level-text:;\n mso-level-tab-stop:none;\n mso-level-number-position:left;\n text-indent:-18.0pt;\n font-family:Symbol;}\n@list l0:level2\n {mso-level-number-format:bullet;\n mso-level-text:o;\n mso-level-tab-stop:none;\n mso-level-number-position:left;\n text-indent:-18.0pt;\n font-family:\"Courier New\";}\n@list l0:level3\n {mso-level-number-format:bullet;\n mso-level-text:;\n mso-level-tab-stop:none;\n mso-level-number-position:left;\n text-indent:-18.0pt;\n font-family:Wingdings;}\n@list l0:level4\n {mso-level-number-format:bullet;\n mso-level-text:;\n mso-level-tab-stop:none;\n mso-level-number-position:left;\n text-indent:-18.0pt;\n font-family:Symbol;}\n@list l0:level5\n {mso-level-number-format:bullet;\n mso-level-text:o;\n mso-level-tab-stop:none;\n mso-level-number-position:left;\n text-indent:-18.0pt;\n font-family:\"Courier New\";}\n@list l0:level6\n {mso-level-number-format:bullet;\n mso-level-text:;\n mso-level-tab-stop:none;\n mso-level-number-position:left;\n text-indent:-18.0pt;\n font-family:Wingdings;}\n@list l0:level7\n {mso-level-number-format:bullet;\n mso-level-text:;\n mso-level-tab-stop:none;\n mso-level-number-position:left;\n text-indent:-18.0pt;\n font-family:Symbol;}\n@list l0:level8\n {mso-level-number-format:bullet;\n mso-level-text:o;\n mso-level-tab-stop:none;\n mso-level-number-position:left;\n text-indent:-18.0pt;\n font-family:\"Courier New\";}\n@list l0:level9\n {mso-level-number-format:bullet;\n mso-level-text:;\n mso-level-tab-stop:none;\n mso-level-number-position:left;\n text-indent:-18.0pt;\n font-family:Wingdings;}\nol\n {margin-bottom:0cm;}\nul\n {margin-bottom:0cm;}\n-->\n</style>\n<!--[if gte mso 10]>\n<style>\n /* Style Definitions */\ntable.MsoNormalTable\n {mso-style-name:\"Normale Tabelle\";\n mso-tstyle-rowband-size:0;\n mso-tstyle-colband-size:0;\n mso-style-noshow:yes;\n mso-style-priority:99;\n mso-style-parent:\"\";\n mso-padding-alt:0cm 5.4pt 0cm 5.4pt;\n mso-para-margin:0cm;\n mso-para-margin-bottom:.0001pt;\n mso-pagination:widow-orphan;\n font-size:12.0pt;\n font-family:Calibri;\n mso-ascii-font-family:Calibri;\n mso-ascii-theme-font:minor-latin;\n mso-hansi-font-family:Calibri;\n mso-hansi-theme-font:minor-latin;\n mso-fareast-language:EN-US;}\n</style>\n<![endif]-->\n</head>\n\n<body bgcolor=white lang=DE style='tab-interval:35.4pt'>\n<!--StartFragment-->\n\n<p class=MsoListParagraphCxSpFirst style='text-indent:-18.0pt;mso-list:l0 level1 lfo1'><![if !supportLists]><span\nstyle='font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:\nSymbol'><span style='mso-list:Ignore'>·<span style='font:7.0pt \"Times New Roman\"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n</span></span></span><![endif]>Test 1<o:p></o:p></p>\n\n<p class=MsoListParagraphCxSpMiddle style='text-indent:-18.0pt;mso-list:l0 level1 lfo1'><![if !supportLists]><span\nstyle='font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:\nSymbol'><span style='mso-list:Ignore'>·<span style='font:7.0pt \"Times New Roman\"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n</span></span></span><![endif]>Test 2<o:p></o:p></p>\n\n<p class=MsoListParagraphCxSpMiddle style='text-indent:-18.0pt;mso-list:l0 level1 lfo1'><![if !supportLists]><span\nstyle='font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:\nSymbol'><span style='mso-list:Ignore'>·<span style='font:7.0pt \"Times New Roman\"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n</span></span></span><![endif]><i style='mso-bidi-font-style:normal'>Test 3<o:p></o:p></i></p>\n\n<p class=MsoListParagraphCxSpMiddle style='text-indent:-18.0pt;mso-list:l0 level1 lfo1'><![if !supportLists]><span\nstyle='font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:\nSymbol'><span style='mso-list:Ignore'>·<span style='font:7.0pt \"Times New Roman\"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n</span></span></span><![endif]>Test 4<o:p></o:p></p>\n\n<p class=MsoListParagraphCxSpLast style='text-indent:-18.0pt;mso-list:l0 level1 lfo1'><![if !supportLists]><span\nstyle='font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:\nSymbol'><span style='mso-list:Ignore'>·<span style='font:7.0pt \"Times New Roman\"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\n</span></span></span><![endif]><b style='mso-bidi-font-weight:normal'>Test5<o:p></o:p></b></p>\n\n<!--EndFragment-->\n</body>\n\n</html>"
  533. should = "<ul><li>Test 1</li><li>Test 2</li><li><i>Test 3</i></li><li>Test 4</li><li><b>Test5</b></li></ul>"
  534. result = App.Utils.htmlCleanup(source)
  535. assert.equal(result.html().trim(), should, source)
  536. source = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n<html>\n<head>\n <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/>\n <title></title>\n <meta name=\"generator\" content=\"LibreOffice 4.4.7.2 (MacOSX)\"/>\n <style type=\"text/css\">\n @page { margin: 0.79in }\n p { margin-bottom: 0.1in; line-height: 120% }\n a:link { so-language: zxx }\n </style>\n</head>\n<body lang=\"en-US\" dir=\"ltr\">\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\">1.\nGehe a<b>uf </b><b>https://www.pfe</b>rdiathek.ge</p>\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\"><br/>\n\n</p>\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\">2.\nMel<font color=\"#800000\">de Dich mit folgende</font> Zugangsdaten an:</p>\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\">Benutzer:\nme@xxx.net</p>\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\">Passwort:\nxxx.</p>\n</body>\n</html>"
  537. should = "\n\n\n \n \n \n \n\n\n<p>1.\nGehe a<b>uf </b><b>https://www.pfe</b>rdiathek.ge</p>\n<p><br>\n\n</p>\n<p>2.\nMel<font color=\"#800000\">de Dich mit folgende</font> Zugangsdaten an:</p>\n<p>Benutzer:\nme@xxx.net</p>\n<p>Passwort:\nxxx.</p>\n\n"
  538. result = App.Utils.htmlCleanup(source)
  539. assert.equal(result.html(), should, source)
  540. source = "<table bgcolor=\"green\" aaa=\"1\"><thead><tr><th colspan=\"2\" abc=\"a\">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>"
  541. should = "<table bgcolor=\"green\"><thead><tr><th colspan=\"2\">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>"
  542. result = App.Utils.htmlCleanup(source)
  543. assert.equal(result.get(0).outerHTML, should, source)
  544. // strip out browser-inserted (broken) link (see https://github.com/zammad/zammad/issues/2019)
  545. source = "<div><a href=\"https://example.com/#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}\">test</a></div>"
  546. should = "<a href=\"#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}\">test</a>"
  547. result = App.Utils.htmlCleanup(source)
  548. assert.equal(result.html(), should, source)
  549. source = "<table bgcolor=\"green\" aaa=\"1\" style=\"color: red\"><thead><tr style=\"margin-top: 10px\"><th colspan=\"2\" abc=\"a\" style=\"margin-top: 12px\">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>"
  550. should = "<table bgcolor=\"green\" style=\"color:red;\"><thead><tr style=\"margin-top:10px;\"><th colspan=\"2\" style=\"margin-top:12px;\">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>"
  551. result = App.Utils.htmlCleanup(source)
  552. result.get(0).outerHTML
  553. //equal(result.get(0).outerHTML, should, source) / string order is different on browsers
  554. assert.equal(result.first().attr('bgcolor'), 'green')
  555. assert.equal(result.first().attr('style'), 'color:red;')
  556. assert.equal(result.first().attr('aaa'), undefined)
  557. assert.equal(result.find('tr').first().attr('style'), 'margin-top:10px;')
  558. assert.equal(result.find('th').first().attr('colspan'), '2')
  559. assert.equal(result.find('th').first().attr('abc'), undefined)
  560. assert.equal(result.find('th').first().attr('style'), 'margin-top:12px;')
  561. source = "<table bgcolor=\"green\" aaa=\"1\" style=\"color:red; display: none;\"><thead><tr><th colspan=\"2\" abc=\"a\">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>"
  562. should = "<table bgcolor=\"green\" style=\"color:red;\"><thead><tr><th colspan=\"2\">aaa</th></tr></thead><tbody><tr><td>value</td></tr></tbody></table>"
  563. result = App.Utils.htmlCleanup(source)
  564. //equal(result.get(0).outerHTML, should, source) / string order is different on browsers
  565. assert.equal(result.first().attr('bgcolor'), 'green')
  566. assert.equal(result.first().attr('style'), 'color:red;')
  567. assert.equal(result.first().attr('aaa'), undefined)
  568. assert.equal(result.find('tr').first().attr('style'), undefined)
  569. assert.equal(result.find('th').first().attr('colspan'), '2')
  570. assert.equal(result.find('th').first().attr('abc'), undefined)
  571. assert.equal(result.find('th').first().attr('style'), undefined)
  572. // https://github.com/zammad/zammad/issues/4445
  573. source = '<meta charset=\'utf-8\'><span style="color: rgb(219, 219, 220);">This is a black font colour with white background</span>'
  574. should = '<span>This is a black font colour with white background</span>'
  575. result = App.Utils.htmlCleanup(source)
  576. assert.equal(result.html(), should, source)
  577. source = '<meta charset=\'utf-8\'><div class="article-content" style="box-sizing: border-box; color: rgb(219, 219, 220); position: relative; z-index: 1; padding: 0px 55px;"><div class="bubble-gap" style="box-sizing: border-box;"><div class="internal-border" style="box-sizing: border-box; padding: 5px; border-radius: 5px; margin: -5px;"><div class="textBubble" style="box-sizing: border-box; padding: 10px 20px; background: var(--background-article-customer); border-radius: 2px; border-color: var(--border-article-customer); box-shadow: none; position: relative;"><div class="textBubble-content" id="article-content-4" data-id="4" style="box-sizing: border-box; overflow: hidden; position: relative;"><div class="richtext-content" style="box-sizing: border-box;"><div style="box-sizing: border-box;">This is a black font colour with white background</div></div></div></div></div></div></div>'
  578. should = '<div><div><div><div><div id="article-content-4"><div><div>This is a black font colour with white background</div></div></div></div></div></div></div>'
  579. result = App.Utils.htmlCleanup(source)
  580. assert.equal(result.html(), should, source)
  581. });
  582. // wrap
  583. QUnit.test("wrap", assert => {
  584. var source = "some text"
  585. var should = 'some text'
  586. var result = App.Utils.wrap(source)
  587. assert.equal(result, should, source)
  588. source = "some text\nsome other text\n"
  589. should = "some text\nsome other text\n"
  590. result = App.Utils.wrap(source)
  591. assert.equal(result, should, source)
  592. source = "some text with some line to wrap"
  593. should = "some text with\nsome line to\nwrap"
  594. result = App.Utils.wrap(source, 14)
  595. assert.equal(result, should, source)
  596. source = "some text\nsome other text\n"
  597. should = "some text\nsome other text\n"
  598. result = App.Utils.wrap(source)
  599. assert.equal(result, should, source)
  600. source = "1234567890 1234567890 1234567890 1234567890"
  601. should = "1234567890 1234567890 1234567890 1234567890"
  602. result = App.Utils.wrap(source)
  603. assert.equal(result, should, source)
  604. source = "123456789012 123456789012 123456789012"
  605. should = "123456789012\n123456789012\n123456789012"
  606. result = App.Utils.wrap(source, 14)
  607. assert.equal(result, should, source)
  608. });
  609. // remove empty lines
  610. QUnit.test("remove empty lines", assert => {
  611. var source = "\ntest 123\n"
  612. var should = "test 123\n"
  613. var result = App.Utils.removeEmptyLines(source)
  614. assert.equal(result, should, source)
  615. source = "\ntest\n\n123\n"
  616. should = "test\n123\n"
  617. result = App.Utils.removeEmptyLines(source)
  618. assert.equal(result, should, source)
  619. });
  620. // quote
  621. QUnit.test("quote", assert => {
  622. var source = "some text"
  623. var should = '> some text'
  624. var result = App.Utils.quote(source)
  625. assert.equal(result, should, source)
  626. source = "some text\nsome other text\n"
  627. should = "> some text\n> some other text"
  628. result = App.Utils.quote(source)
  629. assert.equal(result, should, source)
  630. source = "\n\nsome text\nsome other text\n \n"
  631. should = "> some text\n> some other text"
  632. result = App.Utils.quote(source)
  633. assert.equal(result, should, source)
  634. source = "Welcome!\n\nThank you for installing Zammad.\n\nYou will find ..."
  635. should = "> Welcome!\n>\n> Thank you for installing Zammad.\n>\n> You will find ..."
  636. result = App.Utils.quote(source)
  637. assert.equal(result, should, source)
  638. source = "Welcome! Thank you for installing Zammad. You will find ..."
  639. should = "> Welcome! Thank you\n> for installing\n> Zammad. You will\n> find ..."
  640. result = App.Utils.quote(source, 20)
  641. assert.equal(result, should, source)
  642. });
  643. // check signature
  644. QUnit.test("check signature", assert => {
  645. var message = "<div>test 123 </div>"
  646. var signature = '<div>--<br>Some Signature<br>some department</div>'
  647. var result = App.Utils.signatureCheck(message, signature)
  648. assert.equal(result, true)
  649. message = "<div>test 123 <div>--<br>Some Signature<br>some department\n</div></div>"
  650. signature = '<div>--<br>Some Signature<br>some department</div>'
  651. result = App.Utils.signatureCheck(message, signature)
  652. assert.equal(result, false)
  653. message = "<div>test 123 <div>--<br>Some Signature\n<br>some department\n</div></div>"
  654. signature = '<div>--<br>Some Signature<br>some department</div>'
  655. result = App.Utils.signatureCheck(message, signature)
  656. assert.equal(result, false)
  657. message = "<div>test 123 <div>--<p>Some Signature</p>\n<p><div>some department</div>\n</p>\n</div></div>"
  658. signature = '<div>--<br>Some Signature<br>some department</div>'
  659. result = App.Utils.signatureCheck(message, signature)
  660. assert.equal(result, false)
  661. message = ""
  662. signature = '<div>--<br>Some Signature<br>some department</div>'
  663. result = App.Utils.signatureCheck(message, signature)
  664. assert.equal(result, true)
  665. message = ""
  666. signature = "--\nSome Signature\nsome department"
  667. result = App.Utils.signatureCheck(message, signature)
  668. assert.equal(result, true)
  669. });
  670. QUnit.test('remove signature', assert => {
  671. var message = '<div>test 123 </div>'
  672. var should = '<div>test 123 </div>'
  673. var result = App.Utils.signatureRemoveByHtml(message)
  674. assert.equal(result, should)
  675. var message = '<div>test 123 </div><br>'
  676. var should = '<div>test 123 </div><br>'
  677. var result = App.Utils.signatureRemoveByHtml(message)
  678. assert.equal(result, should)
  679. var message = 'test 123'
  680. var should = 'test 123'
  681. var result = App.Utils.signatureRemoveByHtml(message)
  682. assert.equal(result, should)
  683. var message = '<div>test 123 <div data-signature="true" data-signature-id="1">Test Admin Agent<br>-----</div></div>'
  684. var should = '<div>test 123 </div>'
  685. var result = App.Utils.signatureRemoveByHtml(message)
  686. assert.equal(result, should)
  687. var message = '<div>test 123 <br><div data-signature="true" data-signature-id="1">Test Admin Agent<br>-----</div></div>'
  688. var should = '<div>test 123 </div>'
  689. var result = App.Utils.signatureRemoveByHtml(message)
  690. assert.equal(result, should)
  691. var message = '<div>test 123 <br><br><div data-signature="true" data-signature-id="1">Test Admin Agent<br>-----</div></div>'
  692. var should = '<div>test 123 </div>'
  693. var result = App.Utils.signatureRemoveByHtml(message)
  694. assert.equal(result, should)
  695. var message = 'test 123<br><div data-signature="true" data-signature-id="1">Test Admin Agent<br>-----</div>'
  696. var should = 'test 123'
  697. var result = App.Utils.signatureRemoveByHtml(message)
  698. assert.equal(result, should)
  699. })
  700. // identify signature
  701. QUnit.test("identify signature by plaintext", assert => {
  702. var message = "<div>test 123 </div>"
  703. var should = '<div>test 123 </div>'
  704. var result = App.Utils.signatureIdentifyByPlaintext(message)
  705. assert.equal(result, should)
  706. message = "<div>test 123 <br/>--<br/>Bob Smith</div>"
  707. should = '<div>test 123 <br/>--<br/>Bob Smith</div>'
  708. result = App.Utils.signatureIdentifyByPlaintext(message)
  709. assert.equal(result, should)
  710. message = "<div>test 123 <br/>1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/><br/>--<br/>Bob Smith</div>"
  711. should = '<div>test 123 <br/>1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/><br/><span class="js-signatureMarker"></span>--<br/>Bob Smith</div>'
  712. result = App.Utils.signatureIdentifyByPlaintext(message)
  713. assert.equal(result, should)
  714. message = "<div>test 123 <br/><br/>--no not match--<br/>--<br/>Bob Smith</div>"
  715. should = '<div>test 123 <br/><br/>--no not match--<br/><span class="js-signatureMarker"></span>--<br/>Bob Smith</div>'
  716. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  717. assert.equal(result, should)
  718. message = "<div>test 123 <br/><br/>--no not match--<br/> -- <br/>Bob Smith</div>"
  719. should = '<div>test 123 <br/><br/>--no not match--<br/><span class="js-signatureMarker"></span> -- <br/>Bob Smith</div>'
  720. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  721. assert.equal(result, should)
  722. message = "<div>test 123 <br/><br/>--<br/>Bob Smith<br/><br/><br/><br/><br/>--<br/>Bob Smith</div>"
  723. should = '<div>test 123 <br/><br/><span class="js-signatureMarker"></span>--<br/>Bob Smith<br/><br/><br/><br/><br/>--<br/>Bob Smith</div>'
  724. //should = '<div>test 123 <br><br><br><br><br><br><br><br><br><br><br><span class="js-signatureMarker"></span>--<br>Bob Smith<br/><br/><br/><br/><br/>--<br/>Bob Smith</div>'
  725. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  726. assert.equal(result, should)
  727. message = "<div>test 123</div><div>test 123</div><div>--</div><div>Bob Smith</div>"
  728. should = "<div>test 123</div><div>test 123</div><div><span class=\"js-signatureMarker\"></span>--</div><div>Bob Smith</div>"
  729. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  730. assert.equal(result, should)
  731. message = "<p><span>test 123</span></p><p><span>test 123</span></p><p><span>--</span></p><p><span>Bob Smith</span></p><div></div>"
  732. should = "<p><span>test 123</span></p><p><span>test 123</span></p><p><span><span class=\"js-signatureMarker\"></span>--</span></p><p><span>Bob Smith</span></p><div></div>"
  733. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  734. assert.equal(result, should)
  735. message = "Test reply to zammad<br><br>Am 24.10.2016 18:55 schrieb &quot;Android Support&quot; &lt;android-support@example.com&gt;:<br><br>&gt; <u></u><br>&gt; Sehr geehrte Damen"
  736. should = "Test reply to zammad<br><br><span class=\"js-signatureMarker\"></span>Am 24.10.2016 18:55 schrieb &quot;Android Support&quot; &lt;android-support@example.com&gt;:<br><br>&gt; <u></u><br>&gt; Sehr geehrte Damen"
  737. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  738. assert.equal(result, should)
  739. message = "<br>&lt; On 20 Oct 2016, at 12:23, Martin Edenhofer via Zammad Helpdesk wrote:<br>"
  740. should = "<br><span class=\"js-signatureMarker\"></span>&lt; On 20 Oct 2016, at 12:23, Martin Edenhofer via Zammad Helpdesk wrote:<br>"
  741. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  742. assert.equal(result, should)
  743. // apple
  744. // en
  745. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>On 01/04/15 10:55, Bob Smith wrote:<br/>lalala<p>--</p>some test</div>"
  746. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class="js-signatureMarker"></span>On 01/04/15 10:55, Bob Smith wrote:<br/>lalala<p>--</p>some test</div>'
  747. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  748. assert.equal(result, should)
  749. // de
  750. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>Am 03.04.2015 um 20:58 schrieb Bob Smith &lt;bob@example.com&gt;:<br/>lalala</div>"
  751. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class="js-signatureMarker"></span>Am 03.04.2015 um 20:58 schrieb Bob Smith &lt;bob@example.com&gt;:<br/>lalala</div>'
  752. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  753. assert.equal(result, should)
  754. // ms
  755. // en
  756. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>From: Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Sent: Donnerstag, 2. April 2015 10:00<br/>lalala</div>"
  757. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>From: Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Sent: Donnerstag, 2. April 2015 10:00<br/>lalala</div>'
  758. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  759. assert.equal(result, should)
  760. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>From: Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Sent: Donnerstag, 2. April 2015 10:00<br/>Subject: lalala</div>"
  761. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class="js-signatureMarker"></span>From: Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Sent: Donnerstag, 2. April 2015 10:00<br/>Subject: lalala</div>'
  762. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  763. assert.equal(result, should)
  764. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>From: Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Sent: Donnerstag, 2. April 2015 10:00<br/>1<br/>2<br/>3<br/>4<br/>4<br/>Subject: lalala</div>"
  765. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>From: Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Sent: Donnerstag, 2. April 2015 10:00<br/>1<br/>2<br/>3<br/>4<br/>4<br/>Subject: lalala</div>'
  766. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  767. assert.equal(result, should)
  768. // de
  769. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>Von: Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Gesendet: Donnerstag, 2. April 2015 10:00<br/>Betreff: lalala</div>"
  770. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class="js-signatureMarker"></span>Von: Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Gesendet: Donnerstag, 2. April 2015 10:00<br/>Betreff: lalala</div>'
  771. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  772. assert.equal(result, should)
  773. message = "<div>1<br><br></div><div>Von: Martin Edenhofer via Zammad Support [<a href=\"mailto:support@zammad.inc\" title=\"mailto:support@zammad.inc\" target=\"_blank\">mailto:support@zammad.inc</a>]</div>\n<div>Gesendet: Donnerstag, 2. April 2015 11:32</div>"
  774. should = "<div>1<br><br></div><div>Von: Martin Edenhofer via Zammad Support [<a href=\"mailto:support@zammad.inc\" title=\"mailto:support@zammad.inc\" target=\"_blank\">mailto:support@zammad.inc</a>]</div>\n<div>Gesendet: Donnerstag, 2. April 2015 11:32</div>"
  775. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  776. assert.equal(result, should)
  777. message = "<div>1<br><br></div><div>Von: Martin Edenhofer via Zammad Support [<a href=\"mailto:support@zammad.inc\" title=\"mailto:support@zammad.inc\" target=\"_blank\">mailto:support@zammad.inc</a>]</div>\n<div>Gesendet: Donnerstag, 2. April 2015 11:32</div><div>Betreff: lalala</div>"
  778. should = "<div>1<br><br></div><div><span class=\"js-signatureMarker\"></span>Von: Martin Edenhofer via Zammad Support [<a href=\"mailto:support@zammad.inc\" title=\"mailto:support@zammad.inc\" target=\"_blank\">mailto:support@zammad.inc</a>]</div>\n<div>Gesendet: Donnerstag, 2. April 2015 11:32</div><div>Betreff: lalala</div>"
  779. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  780. assert.equal(result, should)
  781. message = "<div>1<br><br></div><div>Von: Martin Edenhofer via Zammad Support &lt;<a href=\"mailto:support@zammad.inc\" title=\"mailto:support@zammad.inc\" target=\"_blank\">mailto:support@zammad.inc</a>&gt;</div>\n<div>An: somebody</div><div>Datum: Donnerstag, 2. April 2015 11:32</div><div>Betreff: lalala</div>"
  782. should = "<div>1<br><br></div><div><span class=\"js-signatureMarker\"></span>Von: Martin Edenhofer via Zammad Support &lt;<a href=\"mailto:support@zammad.inc\" title=\"mailto:support@zammad.inc\" target=\"_blank\">mailto:support@zammad.inc</a>&gt;</div>\n<div>An: somebody</div><div>Datum: Donnerstag, 2. April 2015 11:32</div><div>Betreff: lalala</div>"
  783. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  784. assert.equal(result, should)
  785. message = "<div>Von: &quot;Johannes Nickel via Zammad Projects&quot; &lt;<a href=\"mailto:projects@zammad.inc\" title=\"mailto:projects@zammad.inc\">projects@zammad.inc</a>&gt;</div><div>An: \"Lisa Smith\" &lt;<a href=\"mailto:lisa.smith@example.com\" title=\"mailto:lisa.smith@example.com\">lisa.smith@example.com</a>&gt;</div><div>Gesendet: Donnerstag, 2. April 2015 10:11:12</div><div>Betreff: Angebot Redundanz / Paket mit Silver Subscription [Ticket#424242]</div><div><br></div><div>Hallo Frau Smith,</div>"
  786. should = "<div><span class=\"js-signatureMarker\"></span>Von: &quot;Johannes Nickel via Zammad Projects&quot; &lt;<a href=\"mailto:projects@zammad.inc\" title=\"mailto:projects@zammad.inc\">projects@zammad.inc</a>&gt;</div><div>An: \"Lisa Smith\" &lt;<a href=\"mailto:lisa.smith@example.com\" title=\"mailto:lisa.smith@example.com\">lisa.smith@example.com</a>&gt;</div><div>Gesendet: Donnerstag, 2. April 2015 10:11:12</div><div>Betreff: Angebot Redundanz / Paket mit Silver Subscription [Ticket#424242]</div><div><br></div><div>Hallo Frau Smith,</div>"
  787. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  788. assert.equal(result, should)
  789. message = "<div>Hi Johannes,</div><div><br></div><div>das Angebot für den halben Tag bitte an uns.</div><div>Der Termin hat sich jetzt auf 10-12 Uhr verschoben, hab ich dir weitergeleitet.</div><div><br></div><div>Viele Grüße</div><div>Max</div><div><br></div><div>&gt; On 07 Oct 2015, at 11:55, Johannes Smith &lt;<a href=mailto:smith@example.com title=mailto:smith@example.com target=_blank>smith@example.com</a> &lt;<a href=mailto:smith@example.com title=mailto:smith@example.com target=_blank>mailto:smith@example.com</a>&gt;&gt; wrote:</div><div>&gt;</div><div>&gt; Hi,</div><div>&gt;</div><div>&gt; assert.OK. Wer kriegt das Angebot? Ist das wirklich nur ein halber Tag?</div></div>"
  790. should = "<div>Hi Johannes,</div><div><br></div><div>das Angebot für den halben Tag bitte an uns.</div><div>Der Termin hat sich jetzt auf 10-12 Uhr verschoben, hab ich dir weitergeleitet.</div><div><br></div><div>Viele Grüße</div><div>Max</div><div><br></div><div><span class=\"js-signatureMarker\"></span>&gt; On 07 Oct 2015, at 11:55, Johannes Smith &lt;<a href=mailto:smith@example.com title=mailto:smith@example.com target=_blank>smith@example.com</a> &lt;<a href=mailto:smith@example.com title=mailto:smith@example.com target=_blank>mailto:smith@example.com</a>&gt;&gt; wrote:</div><div>&gt;</div><div>&gt; Hi,</div><div>&gt;</div><div>&gt; assert.OK. Wer kriegt das Angebot? Ist das wirklich nur ein halber Tag?</div></div>"
  791. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  792. assert.equal(result, should)
  793. message = "Dear Mr. Smith,<div><br></div><div>it seems to be, dass Sie den AutoIncrement Nummerngenerator für Ihre ITSMChangeManagement Installation verwenden. Seit ABC 3.2 wird führend vor der sich in der Datei&nbsp;<span style=\"line-height: 1.45; background-color: initial;\">&lt;ABC_CONFIG_Home&gt;/war/log/ITSMChangeCounter.log &nbsp;befindenden Zahl die SystemID (SysConfig) geschrieben. Dies ist ein Standardverhalten, dass auch bei der Ticketnummer verwendet wird.<br><br>Please ask me if you have questions.</span></div><div><span style=\"line-height: 1.45; background-color: initial;\"><br></span></div><div><span style=\"line-height: 1.45; background-color: initial;\">Viele Grüße,</span></div><div><div data-signature=\"true\" data-signature-id=\"1\">&nbsp; Thorsten Smith\n<br>\n<br>--\n<br>Enterprise Services for ABC\n<br>\n<br>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany\n<br>\n<br>P: +49 (0) 30 111 111 111-0\n<br>F: +49 (0) 30 111 111 111-8\n<br>W: http://zammad.com \n<br>\n<br>Location: Berlin - HRB 12345678 B Amtsgericht Berlin-Charlottenburg\n<br>Managing Director: Martin Edenhofer\n<br></div></div>"
  794. should = "Dear Mr. Smith,<div><br></div><div>it seems to be, dass Sie den AutoIncrement Nummerngenerator für Ihre ITSMChangeManagement Installation verwenden. Seit ABC 3.2 wird führend vor der sich in der Datei&nbsp;<span style=\"line-height: 1.45; background-color: initial;\">&lt;ABC_CONFIG_Home&gt;/war/log/ITSMChangeCounter.log &nbsp;befindenden Zahl die SystemID (SysConfig) geschrieben. Dies ist ein Standardverhalten, dass auch bei der Ticketnummer verwendet wird.<br><br>Please ask me if you have questions.</span></div><div><span style=\"line-height: 1.45; background-color: initial;\"><br></span></div><div><span style=\"line-height: 1.45; background-color: initial;\">Viele Grüße,</span></div><div><span class=\"js-signatureMarker\"></span><div data-signature=\"true\" data-signature-id=\"1\">&nbsp; Thorsten Smith\n<br>\n<br>--\n<br>Enterprise Services for ABC\n<br>\n<br>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany\n<br>\n<br>P: +49 (0) 30 111 111 111-0\n<br>F: +49 (0) 30 111 111 111-8\n<br>W: http://zammad.com \n<br>\n<br>Location: Berlin - HRB 12345678 B Amtsgericht Berlin-Charlottenburg\n<br>Managing Director: Martin Edenhofer\n<br></div></div>"
  795. result = App.Utils.signatureIdentifyByPlaintext(message, true, true)
  796. assert.equal(result, should)
  797. message = "Dear Mr. Smith, nice to read you,<div><div data-signature=\"true\" data-signature-id=\"1\">&nbsp; Thorsten Smith\n<br>\n<br>--\n</div></div>"
  798. should = "Dear Mr. Smith, nice to read you,<div><span class=\"js-signatureMarker\"></span><div data-signature=\"true\" data-signature-id=\"1\">&nbsp; Thorsten Smith\n<br>\n<br>--\n</div></div>"
  799. result = App.Utils.signatureIdentifyByPlaintext(message, true, true)
  800. assert.equal(result, should)
  801. message = "Dear Mr. Smith, nice to read you,<div><div data-signature=\"true\" data-signature-id=\"9999\">&nbsp; Thorsten Smith\n<br>\n<br>--\n</div></div>"
  802. should = "Dear Mr. Smith, nice to read you,<div><div data-signature=\"true\" data-signature-id=\"9999\">&nbsp; Thorsten Smith\n<br>\n<br>--\n</div></div>"
  803. result = App.Utils.signatureIdentifyByPlaintext(message, false, true)
  804. assert.equal(result, should)
  805. // fr
  806. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>De : Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Envoyé : mercredi 29 avril 2015 17:31<br/>Objet : lalala</div>"
  807. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class="js-signatureMarker"></span>De : Martin Edenhofer via Zammad Support [mailto:support@zammad.inc]<br/>Envoyé : mercredi 29 avril 2015 17:31<br/>Objet : lalala</div>'
  808. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  809. assert.equal(result, should)
  810. // thunderbird
  811. // de
  812. message = "<div><br></div><div>Viele Grüße,</div><div>Christian</div><div><br></div><div>Am 04.03.2015 um 12:47 schrieb Martin Edenhofer via Zammad Sales:</div><div>&gt; Hallo Christian,</div>"
  813. should = "<div><br></div><div>Viele Grüße,</div><div>Christian</div><div><br></div><div><span class=\"js-signatureMarker\"></span>Am 04.03.2015 um 12:47 schrieb Martin Edenhofer via Zammad Sales:</div><div>&gt; Hallo Christian,</div>"
  814. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  815. assert.equal(result, should)
  816. // en - Thunderbird default - http://kb.mozillazine.org/Reply_header_settings
  817. message = "<div><br></div><div>Viele Grüße,</div><div>Christian</div><div><br></div><div>On 01-01-2007 11:00 AM, Alf Aardvark wrote:</div><div>&gt; Hallo Christian,</div>"
  818. should = "<div><br></div><div>Viele Grüße,</div><div>Christian</div><div><br></div><div><span class=\"js-signatureMarker\"></span>On 01-01-2007 11:00 AM, Alf Aardvark wrote:</div><div>&gt; Hallo Christian,</div>"
  819. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  820. assert.equal(result, should)
  821. // en - http://kb.mozillazine.org/Reply_header_settings
  822. message = "<div><br></div><div>Viele Grüße,</div><div>Christian</div><div><br></div><div>Alf Aardvark wrote, on 01-01-2007 11:00 AM:</div><div>&gt; Hallo Christian,</div>"
  823. should = "<div><br></div><div>Viele Grüße,</div><div>Christian</div><div><br></div><div><span class=\"js-signatureMarker\"></span>Alf Aardvark wrote, on 01-01-2007 11:00 AM:</div><div>&gt; Hallo Christian,</div>"
  824. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  825. assert.equal(result, should)
  826. // otrs
  827. // en
  828. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>01/04/15 10:55 - Bob Smith wrote:<br/>lalala</div>"
  829. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class="js-signatureMarker"></span>01/04/15 10:55 - Bob Smith wrote:<br/>lalala</div>'
  830. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  831. assert.equal(result, should)
  832. // de
  833. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>01/04/15 10:55 - Bob Smith schrieb:<br/>lalala</div>"
  834. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class="js-signatureMarker"></span>01/04/15 10:55 - Bob Smith schrieb:<br/>lalala</div>'
  835. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  836. assert.equal(result, should)
  837. message = "<div>test 123 <br/><br/></div><div>24.02.2015 14:20 - Roy Kaldung via Zammad Sales schrieb: &nbsp;</div>"
  838. should = "<div>test 123 <br/><br/></div><div><span class=\"js-signatureMarker\"></span>24.02.2015 14:20 - Roy Kaldung via Zammad Sales schrieb: &nbsp;</div>"
  839. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  840. assert.equal(result, should)
  841. // zammad
  842. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><div data-signature=\"true\" data-signature-id=\"5\">lalala</div></div>"
  843. should = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class=\"js-signatureMarker\"></span><div data-signature=\"true\" data-signature-id=\"5\">lalala</div></div>"
  844. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  845. assert.equal(result, should)
  846. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><blockquote type=\"cite\">lalala</blockquote></div>"
  847. should = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class=\"js-signatureMarker\"></span><blockquote type=\"cite\">lalala</blockquote></div>"
  848. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  849. assert.equal(result, should)
  850. // gmail
  851. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><blockquote class=\"ecxgmail_quote\">lalala</blockquote></div>"
  852. should = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class=\"js-signatureMarker\"></span><blockquote class=\"ecxgmail_quote\">lalala</blockquote></div>"
  853. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  854. assert.equal(result, should)
  855. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><blockquote class=\"gmail_quote\">lalala</blockquote></div>"
  856. should = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class=\"js-signatureMarker\"></span><blockquote class=\"gmail_quote\">lalala</blockquote></div>"
  857. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  858. assert.equal(result, should)
  859. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>Am 24. Dezember 2015 um 07:45 schrieb kathrine &lt;kathrine@example.com&gt;:<br/>lalala</div>"
  860. should = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class=\"js-signatureMarker\"></span>Am 24. Dezember 2015 um 07:45 schrieb kathrine &lt;kathrine@example.com&gt;:<br/>lalala</div>"
  861. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  862. assert.equal(result, should)
  863. // word 14
  864. // en
  865. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>Bob Smith wrote:<br/>lalala</div>"
  866. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class="js-signatureMarker"></span>Bob Smith wrote:<br/>lalala</div>'
  867. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  868. assert.equal(result, should)
  869. // de
  870. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>Bob Smith schrieb:<br/>lalala</div>"
  871. should = '<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><span class="js-signatureMarker"></span>Bob Smith schrieb:<br/>lalala</div>'
  872. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  873. assert.equal(result, should)
  874. });
  875. QUnit.test("identify signature by HTML", assert => {
  876. var message = "<div>test 123 </div>"
  877. var should = message
  878. var result = App.Utils.signatureIdentifyByHtml(message)
  879. assert.equal(result, should)
  880. // test if, according to jQuery, invalid HTML does not cause a a crash
  881. // https://github.com/zammad/zammad/issues/3393
  882. message = "<td></td><table></table><div>test 123 </div>"
  883. should = message
  884. result = App.Utils.signatureIdentifyByHtml(message)
  885. assert.equal(result, should)
  886. // simple case 1
  887. message = '<div>actual content</div><blockquote>quoted content</blockquote>'
  888. should = '<div>actual content</div><span class="js-signatureMarker"></span><blockquote>quoted content</blockquote>'
  889. result = App.Utils.signatureIdentifyByHtml(message)
  890. assert.equal(result, should)
  891. // simple case 2
  892. message = '<div>actual content</div><blockquote>quoted content</blockquote><br><div><br></div><div><br> </div>'
  893. should = '<div>actual content</div><span class="js-signatureMarker"></span><blockquote>quoted content</blockquote><br><div><br></div><div><br> </div>'
  894. result = App.Utils.signatureIdentifyByHtml(message)
  895. assert.equal(result, should)
  896. // simple case 3
  897. message = '<div>actual content</div><blockquote>quoted content</blockquote><br><div>actual content 2</div>'
  898. should = message
  899. result = App.Utils.signatureIdentifyByHtml(message)
  900. assert.equal(result, should)
  901. // simple case 4
  902. message = ' content 0 <div>content 1</div> content 2 <blockquote>quoted content</blockquote><br><div><br></div><div><br> </div>'
  903. should = ' content 0 <div>content 1</div> content 2 <span class="js-signatureMarker"></span><blockquote>quoted content</blockquote><br><div><br></div><div><br> </div>'
  904. result = App.Utils.signatureIdentifyByHtml(message)
  905. assert.equal(result, should)
  906. // Invalid html signature detection for exchange warning boxes #3571
  907. message = '<div><span style="color:#9c6500;">CAUTION:</span> This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.</div><br><div><p>actual content</p><div><p>actual content 2</p></div><p>&nbsp;</p><div><p>actual quote</p></div><div><blockquote><p>actual quote</p></blockquote></div><div><p>&nbsp;</p></div><p>&nbsp;</p></div></div>'
  908. should = '<div><span style="color:#9c6500;">CAUTION:</span> This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.</div><br><div><p>actual content</p><div><p>actual content 2</p></div><p>&nbsp;</p><div><p>actual quote</p></div><div><blockquote><p>actual quote</p></blockquote></div><div><p>&nbsp;</p></div><p>&nbsp;</p></div></div>'
  909. result = App.Utils.signatureIdentifyByHtml(message)
  910. assert.equal(result, should)
  911. // Invalid html signature detection for exchange warning boxes #3571
  912. message = '<div>CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.</div><br><div><p>actual content</p><div><p>actual content 2</p></div><p>&nbsp;</p><div><p>actual quote</p></div><div><blockquote><p>actual quote</p></blockquote></div><div><p>&nbsp;</p></div><p>&nbsp;</p></div></div>'
  913. should = '<div>CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.</div><br><div><p>actual content</p><div><p>actual content 2</p></div><p>&nbsp;</p><div><p>actual quote</p></div><div><blockquote><p>actual quote</p></blockquote></div><div><p>&nbsp;</p></div><p>&nbsp;</p></div></div>'
  914. result = App.Utils.signatureIdentifyByHtml(message)
  915. assert.equal(result, should)
  916. // Gmail via Safari on MacOS 10.12
  917. message = '<div dir="ltr">Reply with <b>gmail</b> via Safari on MacOS 10.12</div><br>\
  918. <div>\
  919. <div dir="ltr">Am Mi., 5. Sep. 2018 um 09:22 Uhr schrieb Billy Zhou &lt;bz@zammad.com&gt;:<br>\
  920. </div>\
  921. <blockquote>test email content<br>\
  922. <br>\
  923. </blockquote>\
  924. </div>'
  925. should = '<div dir="ltr">Reply with <b>gmail</b> via Safari on MacOS 10.12</div><br>\
  926. <span class=\"js-signatureMarker\"></span><div>\
  927. <div dir="ltr">Am Mi., 5. Sep. 2018 um 09:22 Uhr schrieb Billy Zhou &lt;bz@zammad.com&gt;:<br>\
  928. </div>\
  929. <blockquote>test email content<br>\
  930. <br>\
  931. </blockquote>\
  932. </div>'
  933. result = App.Utils.signatureIdentifyByHtml(message)
  934. assert.equal(result, should)
  935. // Yahoo Mail via Safari on MacOS 10.12
  936. message = '<div style="color:#000; background-color:#fff; font-family:Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif;font-size:16px"><div id="yui_3_16_0_ym19_1_1536132243868_2594"><span id="yui_3_16_0_ym19_1_1536132243868_2593">Reply with <b id="yui_3_16_0_ym19_1_1536132243868_2597">Yahoo Mail</b> via Safari on MacOS 10.12</span></div> <div class="qtdSeparateBR"><br><br></div><div class="yahoo_quoted" style="display: block;"> <div style="font-family: Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif; font-size: 16px;"> <div style="font-family: HelveticaNeue, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif; font-size: 16px;"> <div dir="ltr"><font size="2" face="Arial"> Billy Zhou &lt;bz@zammad.com&gt; schrieb am 9:08 Mittwoch, 5.September 2018:<br></font></div> <br><br> <div class="y_msg_container"><div dir="ltr">test email content<br></div><div dir="ltr"><br></div><br><br></div> </div> </div> </div></div>'
  937. should = '<div style="color:#000; background-color:#fff; font-family:Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif;font-size:16px"><div id="yui_3_16_0_ym19_1_1536132243868_2594"><span id="yui_3_16_0_ym19_1_1536132243868_2593">Reply with <b id="yui_3_16_0_ym19_1_1536132243868_2597">Yahoo Mail</b> via Safari on MacOS 10.12</span></div> <div class="qtdSeparateBR"><br><br></div><span class="js-signatureMarker"></span><div class="yahoo_quoted" style="display: block;"> <div style="font-family: Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif; font-size: 16px;"> <div style="font-family: HelveticaNeue, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif; font-size: 16px;"> <div dir="ltr"><font size="2" face="Arial"> Billy Zhou &lt;bz@zammad.com&gt; schrieb am 9:08 Mittwoch, 5.September 2018:<br></font></div> <br><br> <div class="y_msg_container"><div dir="ltr">test email content<br></div><div dir="ltr"><br></div><br><br></div> </div> </div> </div></div>'
  938. result = App.Utils.signatureIdentifyByHtml(message)
  939. assert.equal(result, should)
  940. // Thunderbird 52 on MacOS 10.12
  941. message = 'Reply with <b>Thunderbird 52</b> on MacOS 10.12<br>\
  942. <br>\
  943. <div class="moz-cite-prefix">Am 04.09.18 um 15:32 schrieb Billy\
  944. Zhou:<br>\
  945. </div>\
  946. <blockquote type="cite"\
  947. cite="mid:da18ed01-b187-a383-bfe7-72663cf82a83@zammad.com">test\
  948. email content\
  949. <br>\
  950. <br>\
  951. </blockquote>\
  952. <br>'
  953. should = 'Reply with <b>Thunderbird 52</b> on MacOS 10.12<br>\
  954. <br>\
  955. <div class="moz-cite-prefix">Am 04.09.18 um 15:32 schrieb Billy\
  956. Zhou:<br>\
  957. </div>\
  958. <span class=\"js-signatureMarker\"></span><blockquote type="cite" cite="mid:da18ed01-b187-a383-bfe7-72663cf82a83@zammad.com">test\
  959. email content\
  960. <br>\
  961. <br>\
  962. </blockquote>\
  963. <br>'
  964. result = App.Utils.signatureIdentifyByHtml(message)
  965. assert.equal(result, should)
  966. // Apple Mail on MacOS 10
  967. message = '<div class="">Reply by <b class="">Apple Mail</b> on MacOS 10.</div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On 4. Sep 2018, at 15:32, Billy Zhou &lt;<a href="mailto:bz@zammad.com" class="">bz@zammad.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">test email content<br class=""><br class=""></div></div></blockquote></div><br class="">'
  968. should = '<div class="">Reply by <b class="">Apple Mail</b> on MacOS 10.</div><div class=""><br class=""></div><br class=""><span class=\"js-signatureMarker\"></span><div><blockquote type="cite" class=""><div class="">On 4. Sep 2018, at 15:32, Billy Zhou &lt;<a href="mailto:bz@zammad.com" class="">bz@zammad.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">test email content<br class=""><br class=""></div></div></blockquote></div><br class="">'
  969. result = App.Utils.signatureIdentifyByHtml(message)
  970. assert.equal(result, should)
  971. // Office 365 (10325.20118) on Windows 10 Build 1803
  972. // With German marker: -----Ursprüngliche Nachricht-----
  973. // Using fallback to signatureIdentifyByPlaintext
  974. message = '<div>\
  975. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  976. <p> </p>\
  977. <p><b>fett</b></p>\
  978. <p> </p>\
  979. <span class="js-signatureMarker"></span><p>--</p>\
  980. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  981. <p> </p>\
  982. <p>P: +49 (0) 30 55 57 160-0</p>\
  983. <p>F: +49 (0) 30 55 57 160-99</p>\
  984. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  985. <p> </p>\
  986. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  987. <p>Managing Director: Martin Edenhofer</p>\
  988. <p> </p>\
  989. <p>-----Ursprüngliche Nachricht-----<br>Von: Billy Zhou &lt;bz@zammad.com&gt; <br>Gesendet: Dienstag, 4. September 2018 15:33<br>An: me@zammad.com<br>Betreff: test email title</p>\
  990. <p> </p>\
  991. <p>test email content</p>\
  992. <p> </p>\
  993. </div>'
  994. should = '<div>\
  995. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  996. <p> </p>\
  997. <p><b>fett</b></p>\
  998. <p> </p>\
  999. <span class="js-signatureMarker"></span><p><span class=\"js-signatureMarker\"></span>--</p>\
  1000. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  1001. <p> </p>\
  1002. <p>P: +49 (0) 30 55 57 160-0</p>\
  1003. <p>F: +49 (0) 30 55 57 160-99</p>\
  1004. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  1005. <p> </p>\
  1006. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  1007. <p>Managing Director: Martin Edenhofer</p>\
  1008. <p> </p>\
  1009. <p>-----Ursprüngliche Nachricht-----<br>Von: Billy Zhou &lt;bz@zammad.com&gt; <br>Gesendet: Dienstag, 4. September 2018 15:33<br>An: me@zammad.com<br>Betreff: test email title</p>\
  1010. <p> </p>\
  1011. <p>test email content</p>\
  1012. <p> </p>\
  1013. </div>'
  1014. result = App.Utils.signatureIdentifyByHtml(message)
  1015. assert.equal(result, should)
  1016. // Office 365 (10325.20118) on Windows 10 Build 1803
  1017. // With English marker: -----Original Message-----
  1018. // Using fallback to signatureIdentifyByPlaintext
  1019. message = '<div>\
  1020. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  1021. <p> </p>\
  1022. <p><b>fett</b></p>\
  1023. <p> </p>\
  1024. <span class="js-signatureMarker"></span><p>--</p>\
  1025. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  1026. <p> </p>\
  1027. <p>P: +49 (0) 30 55 57 160-0</p>\
  1028. <p>F: +49 (0) 30 55 57 160-99</p>\
  1029. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  1030. <p> </p>\
  1031. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  1032. <p>Managing Director: Martin Edenhofer</p>\
  1033. <p> </p>\
  1034. <p>-----Original Message-----<br>Von: Billy Zhou &lt;bz@zammad.com&gt; <br>Gesendet: Dienstag, 4. September 2018 15:33<br>An: me@zammad.com<br>Betreff: test email title</p>\
  1035. <p> </p>\
  1036. <p>test email content</p>\
  1037. <p> </p>\
  1038. </div>'
  1039. should = '<div>\
  1040. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  1041. <p> </p>\
  1042. <p><b>fett</b></p>\
  1043. <p> </p>\
  1044. <span class="js-signatureMarker"></span><p><span class=\"js-signatureMarker\"></span>--</p>\
  1045. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  1046. <p> </p>\
  1047. <p>P: +49 (0) 30 55 57 160-0</p>\
  1048. <p>F: +49 (0) 30 55 57 160-99</p>\
  1049. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  1050. <p> </p>\
  1051. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  1052. <p>Managing Director: Martin Edenhofer</p>\
  1053. <p> </p>\
  1054. <p>-----Original Message-----<br>Von: Billy Zhou &lt;bz@zammad.com&gt; <br>Gesendet: Dienstag, 4. September 2018 15:33<br>An: me@zammad.com<br>Betreff: test email title</p>\
  1055. <p> </p>\
  1056. <p>test email content</p>\
  1057. <p> </p>\
  1058. </div>'
  1059. result = App.Utils.signatureIdentifyByHtml(message)
  1060. assert.equal(result, should)
  1061. // Office 365 (10325.20118) on Windows 10 Build 1803
  1062. // With German marker: -----Ursprüngliche Nachricht-----
  1063. // Without any existing <span class="js-signatureMarker"></span>
  1064. // Using fallback to signatureIdentifyByPlaintext
  1065. message = '<div>\
  1066. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  1067. <p> </p>\
  1068. <p><b>fett</b></p>\
  1069. <p> </p>\
  1070. <p>--</p>\
  1071. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  1072. <p> </p>\
  1073. <p>P: +49 (0) 30 55 57 160-0</p>\
  1074. <p>F: +49 (0) 30 55 57 160-99</p>\
  1075. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  1076. <p> </p>\
  1077. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  1078. <p>Managing Director: Martin Edenhofer</p>\
  1079. <p> </p>\
  1080. <p>-----Ursprüngliche Nachricht-----<br>Von: Billy Zhou &lt;bz@zammad.com&gt; <br>Gesendet: Dienstag, 4. September 2018 15:33<br>An: me@zammad.com<br>Betreff: test email title</p>\
  1081. <p> </p>\
  1082. <p>test email content</p>\
  1083. <p> </p>\
  1084. </div>'
  1085. should = '<div>\
  1086. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  1087. <p> </p>\
  1088. <p><b>fett</b></p>\
  1089. <p> </p>\
  1090. <p><span class=\"js-signatureMarker\"></span>--</p>\
  1091. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  1092. <p> </p>\
  1093. <p>P: +49 (0) 30 55 57 160-0</p>\
  1094. <p>F: +49 (0) 30 55 57 160-99</p>\
  1095. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  1096. <p> </p>\
  1097. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  1098. <p>Managing Director: Martin Edenhofer</p>\
  1099. <p> </p>\
  1100. <p>-----Ursprüngliche Nachricht-----<br>Von: Billy Zhou &lt;bz@zammad.com&gt; <br>Gesendet: Dienstag, 4. September 2018 15:33<br>An: me@zammad.com<br>Betreff: test email title</p>\
  1101. <p> </p>\
  1102. <p>test email content</p>\
  1103. <p> </p>\
  1104. </div>'
  1105. result = App.Utils.signatureIdentifyByHtml(message)
  1106. assert.equal(result, should)
  1107. });
  1108. // check attachment references
  1109. QUnit.test("check check attachment reference", assert => {
  1110. var message = 'some not existing'
  1111. var result = false
  1112. var verify = App.Utils.checkAttachmentReference(message)
  1113. assert.equal(verify, result)
  1114. message = 'some attachment for you'
  1115. result = 'attachment'
  1116. verify = App.Utils.checkAttachmentReference(message)
  1117. assert.equal(verify, result)
  1118. message = 'your attachment.'
  1119. result = 'attachment'
  1120. verify = App.Utils.checkAttachmentReference(message)
  1121. assert.equal(verify, result)
  1122. message = 'some otherattachment for you'
  1123. result = false
  1124. verify = App.Utils.checkAttachmentReference(message)
  1125. assert.equal(verify, result)
  1126. message = 'some attachmentother for you'
  1127. result = false
  1128. verify = App.Utils.checkAttachmentReference(message)
  1129. assert.equal(verify, result)
  1130. message = 'someattachment'
  1131. result = false
  1132. verify = App.Utils.checkAttachmentReference(message)
  1133. assert.equal(verify, result)
  1134. message = 'As enclosed you will find.'
  1135. result = 'enclosed'
  1136. verify = App.Utils.checkAttachmentReference(message)
  1137. assert.equal(verify, result)
  1138. message = '<div>Hi Test,</div><div><blockquote>On Monday, 22 July 2019, 14:07:54, Test User wrote:<br><br>Test attachment <br></blockquote></div>'
  1139. result = false
  1140. verify = App.Utils.checkAttachmentReference(message)
  1141. assert.equal(verify, result)
  1142. message = '<div>Hi Test,</div><div><blockquote type="cite">cite attachment </blockquote></div>'
  1143. result = false
  1144. verify = App.Utils.checkAttachmentReference(message)
  1145. assert.equal(verify, result)
  1146. message = '<div>Hi Test,</div><div><blockquote class="ecxgmail_quote">ecxgmail_quote attachment </blockquote></div>'
  1147. result = false
  1148. verify = App.Utils.checkAttachmentReference(message)
  1149. assert.equal(verify, result)
  1150. message = '<div>Hi Test,</div><div data-signature="true">ecxgmail_quote attachment</div>'
  1151. result = false
  1152. verify = App.Utils.checkAttachmentReference(message)
  1153. assert.equal(verify, result)
  1154. });
  1155. // replace tags
  1156. QUnit.test("check replace tags", assert => {
  1157. var formatNumber = function(num, digits) {
  1158. while (num.toString().length < digits) {
  1159. num = '0' + num
  1160. }
  1161. return num
  1162. }
  1163. var formatTimestamp = function(timestamp) {
  1164. localTime = new Date(Date.parse(timestamp))
  1165. d = formatNumber(localTime.getDate(), 2)
  1166. m = formatNumber(localTime.getMonth() + 1, 2)
  1167. yfull = localTime.getFullYear()
  1168. M = formatNumber(localTime.getMinutes(), 2)
  1169. H = formatNumber(localTime.getHours(), 2)
  1170. l = (H + 11) % 12 + 1
  1171. if (l < 10) {
  1172. l = ' ' + l
  1173. }
  1174. P = H >= 12 ? 'pm' : 'am'
  1175. return m + '/' + d + '/' + yfull + ' ' + l + ':' + M + ' ' + P
  1176. }
  1177. var message = "<div>#{user.firstname} #{user.lastname}</div>"
  1178. var result = '<div>Bob Smith</div>'
  1179. var data = {
  1180. user: {
  1181. firstname: 'Bob',
  1182. lastname: 'Smith',
  1183. },
  1184. }
  1185. var verify = App.Utils.replaceTags(message, data)
  1186. assert.equal(verify, result)
  1187. message = "<div>#{user.firstname} #{user.lastname}</div>"
  1188. result = '<div>Bob Smith</div>'
  1189. data = {
  1190. user: {
  1191. firstname: function() { return 'Bob' },
  1192. lastname: function() { return 'Smith' },
  1193. },
  1194. }
  1195. verify = App.Utils.replaceTags(message, data)
  1196. assert.equal(verify, result)
  1197. message = "<div>#{user.firstname} #{user.lastname}</div>"
  1198. result = '<div>Bob -</div>'
  1199. data = {
  1200. user: {
  1201. firstname: 'Bob',
  1202. },
  1203. }
  1204. verify = App.Utils.replaceTags(message, data)
  1205. assert.equal(verify, result)
  1206. message = "<div>#{user.firstname} #{user.lastname}</div>"
  1207. result = '<div>Bob 0</div>'
  1208. data = {
  1209. user: {
  1210. firstname: 'Bob',
  1211. lastname: 0,
  1212. },
  1213. }
  1214. verify = App.Utils.replaceTags(message, data)
  1215. assert.equal(verify, result)
  1216. message = "<div>#{user.firstname} #{user.lastname}</div>"
  1217. result = '<div>Bob -</div>'
  1218. data = {
  1219. user: {
  1220. firstname: 'Bob',
  1221. lastname: '',
  1222. },
  1223. }
  1224. verify = App.Utils.replaceTags(message, data)
  1225. assert.equal(verify, result)
  1226. message = "<div>#{user.firstname} #{user.not.existing.test}</div>"
  1227. result = '<div>Bob -</div>'
  1228. data = {
  1229. user: {
  1230. firstname: 'Bob',
  1231. },
  1232. }
  1233. verify = App.Utils.replaceTags(message, data)
  1234. assert.equal(verify, result)
  1235. message = "<div>#{user.firstname} #{not.existing.test}</div>"
  1236. result = '<div>Bob -</div>'
  1237. data = {
  1238. user: {
  1239. firstname: 'Bob',
  1240. },
  1241. }
  1242. verify = App.Utils.replaceTags(message, data)
  1243. assert.equal(verify, result)
  1244. message = "<div>#{user.firstname} #{not.existing.test}</div>"
  1245. result = '<div>Bob -</div>'
  1246. data = {
  1247. user: {
  1248. firstname: 'Bob',
  1249. not: null,
  1250. },
  1251. }
  1252. verify = App.Utils.replaceTags(message, data)
  1253. assert.equal(verify, result)
  1254. message = "<div>#{user.firstname} #{not.existing.test}</div>"
  1255. result = '<div>Bob -</div>'
  1256. data = {
  1257. user: {
  1258. firstname: 'Bob',
  1259. not: {},
  1260. },
  1261. }
  1262. verify = App.Utils.replaceTags(message, data)
  1263. assert.equal(verify, result)
  1264. message = "<div>#{user.firstname} #{<a href=\"/test\">user.lastname</a>}</div>"
  1265. result = '<div>Bob Smith</div>'
  1266. data = {
  1267. user: {
  1268. firstname: 'Bob',
  1269. lastname: 'Smith',
  1270. },
  1271. }
  1272. verify = App.Utils.replaceTags(message, data)
  1273. assert.equal(verify, result)
  1274. message = "<div>issue #4973 #{user,firstname}</div>"
  1275. result = '<div>issue #4973 -</div>'
  1276. data = {
  1277. user: {
  1278. firstname: 'Bob',
  1279. lastname: 'Smith',
  1280. },
  1281. }
  1282. verify = App.Utils.replaceTags(message, data)
  1283. assert.equal(verify, result)
  1284. user = new App.User({
  1285. firstname: 'Bob',
  1286. lastname: 'Smith Good',
  1287. created_at: '2018-10-31T10:00:00Z',
  1288. })
  1289. message = "<div>#{user.firstname} #{user.created_at}</div>"
  1290. result = '<div>Bob ' + formatTimestamp('2018-10-31T10:00:00Z') + '</div>'
  1291. data = {
  1292. user: user
  1293. }
  1294. verify = App.Utils.replaceTags(message, data)
  1295. assert.equal(verify, result)
  1296. message = "<div>#{user.firstname} #{user.created_at.date}</div>"
  1297. result = '<div>Bob -</div>'
  1298. data = {
  1299. user: user
  1300. }
  1301. verify = App.Utils.replaceTags(message, data)
  1302. assert.equal(verify, result)
  1303. message = "<div>#{user.firstname} #{user.created.date}</div>"
  1304. result = '<div>Bob -</div>'
  1305. data = {
  1306. user: user
  1307. }
  1308. verify = App.Utils.replaceTags(message, data)
  1309. assert.equal(verify, result)
  1310. message = "<a href=\"https://example.co/q=#{user.lastname}\">some text</a>"
  1311. result = '<a href=\"https://example.co/q=Smith%20Good\">some text</a>'
  1312. data = {
  1313. user: user
  1314. }
  1315. verify = App.Utils.replaceTags(message, data, true)
  1316. assert.equal(verify, result)
  1317. var attribute_external_source = {
  1318. name: 'external_data_source', display: 'external_data_source', tag: 'autocompletion_ajax_external_data_source', null: true
  1319. };
  1320. App.Ticket.configure_attributes.push(attribute_external_source)
  1321. data = {
  1322. ticket: {
  1323. external_data_source: {
  1324. value: 1234,
  1325. label: 'Example Label'
  1326. }
  1327. }
  1328. }
  1329. message = "<a href=\"https://example.co/product/#{ticket.external_data_source}\">some text</a>"
  1330. result = '<a href=\"https://example.co/product/1234">some text</a>'
  1331. verify = App.Utils.replaceTags(message, data, true)
  1332. assert.equal(verify, result)
  1333. message = "<a href=\"https://example.co/product/#{ticket.external_data_source.value}\">some text</a>"
  1334. result = '<a href=\"https://example.co/product/Example%20Label">some text</a>'
  1335. verify = App.Utils.replaceTags(message, data, true)
  1336. assert.equal(verify, result)
  1337. data = { ticket: {} }
  1338. message = "Test: #{ticket.external_data_source}"
  1339. result = 'Test: -'
  1340. verify = App.Utils.replaceTags(message, data)
  1341. assert.equal(verify, result)
  1342. data = { ticket: {} }
  1343. message = "Test: #{ticket.external_data_source.value}"
  1344. result = 'Test: -'
  1345. verify = App.Utils.replaceTags(message, data)
  1346. assert.equal(verify, result)
  1347. var attribute_select = {
  1348. name: 'select', display: 'select', tag: 'select', null: true, nulloption: true, options: { a: 'Value A', b: 'Value B' }, value: null, historical_options: { a: 'Value A', b: 'Value B', c: 'Value C' }
  1349. }
  1350. App.Ticket.configure_attributes.push(attribute_select)
  1351. data = {
  1352. ticket: {
  1353. select: 'b',
  1354. }
  1355. }
  1356. message = "Test: #{ticket.select}"
  1357. result = 'Test: b'
  1358. verify = App.Utils.replaceTags(message, data)
  1359. assert.equal(verify, result)
  1360. message = "Test: #{ticket.select.value}"
  1361. result = 'Test: Value B'
  1362. verify = App.Utils.replaceTags(message, data)
  1363. assert.equal(verify, result)
  1364. data = { ticket: {} }
  1365. message = "Test: #{ticket.select}"
  1366. result = 'Test: -'
  1367. verify = App.Utils.replaceTags(message, data)
  1368. assert.equal(verify, result)
  1369. data = { ticket: {} }
  1370. message = "Test: #{ticket.select.value}"
  1371. result = 'Test: -'
  1372. verify = App.Utils.replaceTags(message, data)
  1373. assert.equal(verify, result)
  1374. var attribute_multiselect = {
  1375. name: 'multiselect', display: 'multiselect', tag: 'multiselect', null: true, nulloption: true, options: { a: 'Value A', b: 'Value B', c: 'Value C' }, value: null, historical_options: { a: 'Value A', b: 'Value B', c: 'Value C' }
  1376. }
  1377. App.Ticket.configure_attributes.push(attribute_multiselect)
  1378. data = {
  1379. ticket: {
  1380. multiselect: ['a', 'b'],
  1381. }
  1382. }
  1383. message = "Test: #{ticket.multiselect}"
  1384. result = 'Test: a, b'
  1385. verify = App.Utils.replaceTags(message, data)
  1386. assert.equal(verify, result)
  1387. message = "Test: #{ticket.multiselect.value}"
  1388. result = 'Test: Value A, Value B'
  1389. verify = App.Utils.replaceTags(message, data)
  1390. assert.equal(verify, result)
  1391. data = { ticket: {} }
  1392. message = "Test: #{ticket.multiselect}"
  1393. result = 'Test: -'
  1394. verify = App.Utils.replaceTags(message, data)
  1395. assert.equal(verify, result)
  1396. data = { ticket: {} }
  1397. message = "Test: #{ticket.multiselect.value}"
  1398. result = 'Test: -'
  1399. verify = App.Utils.replaceTags(message, data)
  1400. assert.equal(verify, result)
  1401. var attribute_textarea = {
  1402. name: 'textarea', display: 'textarea', tag: 'textarea', null: true, nulloption: true, value: null
  1403. }
  1404. App.Ticket.configure_attributes.push(attribute_textarea)
  1405. data = {
  1406. ticket: {
  1407. textarea: 'Line 1\nLine 2\nLine 3',
  1408. }
  1409. }
  1410. message = "Test: #{ticket.textarea}"
  1411. result = 'Test: <div>Line 1</div><div>Line 2</div><div>Line 3</div>'
  1412. verify = App.Utils.replaceTags(message, data)
  1413. assert.equal(verify, result)
  1414. message = "Test: #{ticket.textarea.value}"
  1415. result = 'Test: <div>Line 1</div><div>Line 2</div><div>Line 3</div>'
  1416. verify = App.Utils.replaceTags(message, data)
  1417. assert.equal(verify, result)
  1418. data = { ticket: {} }
  1419. message = "Test: #{ticket.textarea}"
  1420. result = 'Test: -'
  1421. verify = App.Utils.replaceTags(message, data)
  1422. assert.equal(verify, result)
  1423. data = { ticket: {} }
  1424. message = "Test: #{ticket.textarea.value}"
  1425. result = 'Test: -'
  1426. verify = App.Utils.replaceTags(message, data)
  1427. assert.equal(verify, result)
  1428. message = "<div>#{user.avatar(100, 100)}</div>"
  1429. result = '<div></div>'
  1430. data = {
  1431. user: user
  1432. }
  1433. verify = App.Utils.replaceTags(message, data)
  1434. assert.equal(verify, result)
  1435. user = new App.User({
  1436. firstname: 'Bob',
  1437. lastname: 'Smith Good',
  1438. created_at: '2018-10-31T10:00:00Z',
  1439. image: '808d0f10f81c8b1117608cb22a73076e'
  1440. })
  1441. message = "<div>#{user.avatar(100, 100)}</div>"
  1442. result = '<div><img src="api/v1/users/image/' + user.image + '" width="100" height="100" data-user-avatar="true" /></div>'
  1443. data = {
  1444. user: user
  1445. }
  1446. verify = App.Utils.replaceTags(message, data)
  1447. assert.equal(verify, result)
  1448. });
  1449. // check attibute validation
  1450. QUnit.test("check attibute validation", assert => {
  1451. var string = '123'
  1452. var result = '123'
  1453. var verify = App.Utils.htmlAttributeCleanup(string)
  1454. assert.equal(verify, result, string)
  1455. string = '123!'
  1456. result = '123'
  1457. verify = App.Utils.htmlAttributeCleanup(string)
  1458. assert.equal(verify, result, string)
  1459. string = '12 3!'
  1460. result = '123'
  1461. verify = App.Utils.htmlAttributeCleanup(string)
  1462. assert.equal(verify, result, string)
  1463. string = '12-3!'
  1464. result = '12-3'
  1465. verify = App.Utils.htmlAttributeCleanup(string)
  1466. assert.equal(verify, result, string)
  1467. string = '12_3!'
  1468. result = '12_3'
  1469. verify = App.Utils.htmlAttributeCleanup(string)
  1470. assert.equal(verify, result, string)
  1471. string = '^12_3!'
  1472. result = '12_3'
  1473. verify = App.Utils.htmlAttributeCleanup(string)
  1474. assert.equal(verify, result, string)
  1475. string = '^1\n 2_3!'
  1476. result = '12_3'
  1477. verify = App.Utils.htmlAttributeCleanup(string)
  1478. assert.equal(verify, result, string)
  1479. string = 'abc?'
  1480. result = 'abc'
  1481. verify = App.Utils.htmlAttributeCleanup(string)
  1482. assert.equal(verify, result, string)
  1483. string = 'abc."'
  1484. result = 'abc'
  1485. verify = App.Utils.htmlAttributeCleanup(string)
  1486. assert.equal(verify, result, string)
  1487. string = '#abc!^'
  1488. result = 'abc'
  1489. verify = App.Utils.htmlAttributeCleanup(string)
  1490. assert.equal(verify, result, string)
  1491. string = 'abc()=$'
  1492. result = 'abc'
  1493. verify = App.Utils.htmlAttributeCleanup(string)
  1494. assert.equal(verify, result, string)
  1495. string = "abc()=$\n123\rß"
  1496. result = 'abc123'
  1497. verify = App.Utils.htmlAttributeCleanup(string)
  1498. assert.equal(verify, result, string)
  1499. });
  1500. // check form diff
  1501. QUnit.test("check form diff", assert => {
  1502. var dataNow = {
  1503. owner_id: 1,
  1504. pending_date: '2015-01-28T09:39:00Z',
  1505. }
  1506. var dataLast = {
  1507. owner_id: '',
  1508. pending_date: '2015-01-28T09:39:00Z',
  1509. }
  1510. var diff = {}
  1511. var result = App.Utils.formDiff(dataNow, dataLast)
  1512. assert.deepEqual(result, diff, 'check form diff')
  1513. dataNow = {
  1514. owner_id: '1',
  1515. pending_date: '2015-01-28T09:39:00Z',
  1516. }
  1517. dataLast = {
  1518. owner_id: '',
  1519. pending_date: '2015-01-28T09:39:00Z',
  1520. }
  1521. diff = {}
  1522. result = App.Utils.formDiff(dataNow, dataLast)
  1523. assert.deepEqual(result, diff, 'check form diff')
  1524. dataNow = {
  1525. pending_date: '2015-01-28T09:39:00Z',
  1526. }
  1527. dataLast = {
  1528. owner_id: 1,
  1529. pending_date: '2015-01-28T09:39:00Z',
  1530. }
  1531. diff = {}
  1532. result = App.Utils.formDiff(dataNow, dataLast)
  1533. assert.deepEqual(result, diff, 'check form diff')
  1534. dataNow = {
  1535. owner_id: '',
  1536. pending_date: '2015-01-28T09:39:00Z',
  1537. }
  1538. dataLast = {
  1539. pending_date: '2015-01-28T09:39:00Z',
  1540. }
  1541. diff = {
  1542. }
  1543. result = App.Utils.formDiff(dataNow, dataLast)
  1544. assert.deepEqual(result, diff, 'check form diff')
  1545. dataNow = {
  1546. owner_id: '',
  1547. state_ids: [1,5,6,7],
  1548. }
  1549. dataLast = {}
  1550. diff = {
  1551. state_ids: ['1','5','6','7'],
  1552. }
  1553. result = App.Utils.formDiff(dataNow, dataLast)
  1554. assert.deepEqual(result, diff, 'check form diff')
  1555. dataNow = {
  1556. owner_id: 1,
  1557. state_ids: [1,5,7,6],
  1558. }
  1559. dataLast = {
  1560. owner_id: '',
  1561. state_ids: [1,5,6,7],
  1562. }
  1563. diff = {}
  1564. result = App.Utils.formDiff(dataNow, dataLast)
  1565. assert.deepEqual(result, diff, 'check form diff')
  1566. dataNow = {
  1567. owner_id: 1,
  1568. state_ids: [1,5,6,7],
  1569. }
  1570. dataLast = {
  1571. state_ids: ['1','5','7'],
  1572. }
  1573. diff = {
  1574. state_ids: ['6'],
  1575. }
  1576. result = App.Utils.formDiff(dataNow, dataLast)
  1577. assert.deepEqual(result, diff, 'check form diff')
  1578. dataNow = {
  1579. owner_id: '',
  1580. state_ids: [1,5,6,7],
  1581. }
  1582. dataLast = {
  1583. owner_id: 1,
  1584. state_ids: [1,5,6,7],
  1585. }
  1586. diff = {}
  1587. result = App.Utils.formDiff(dataNow, dataLast)
  1588. assert.deepEqual(result, diff, 'check form diff')
  1589. dataNow = {
  1590. owner_id: '',
  1591. state_ids: [1,5,6,7],
  1592. }
  1593. dataLast = {
  1594. owner_id: 5,
  1595. state_ids: [1,5,6,7],
  1596. }
  1597. diff = {
  1598. owner_id: ''
  1599. }
  1600. result = App.Utils.formDiff(dataNow, dataLast)
  1601. assert.deepEqual(result, diff, 'check form diff')
  1602. dataNow = {
  1603. state_id: 4,
  1604. pending_time: '2015-01-28T11:34:00Z'
  1605. }
  1606. dataLast = {
  1607. state_id: 5,
  1608. pending_time: undefined
  1609. }
  1610. diff = {
  1611. state_id: '4',
  1612. pending_time: '2015-01-28T11:34:00Z'
  1613. }
  1614. result = App.Utils.formDiff(dataNow, dataLast)
  1615. assert.deepEqual(result, diff, 'check form diff')
  1616. dataNow = {
  1617. pending_time: undefined
  1618. }
  1619. dataLast = {
  1620. pending_time: null
  1621. }
  1622. diff = {}
  1623. result = App.Utils.formDiff(dataNow, dataLast)
  1624. assert.deepEqual(result, diff, 'check form diff')
  1625. dataNow = {
  1626. ticket: {
  1627. pending_time: undefined,
  1628. },
  1629. }
  1630. dataLast = {
  1631. ticket: {
  1632. pending_time: null,
  1633. },
  1634. }
  1635. diff = {}
  1636. result = App.Utils.formDiff(dataNow, dataLast)
  1637. assert.deepEqual(result, diff, 'check form diff')
  1638. dataNow = {
  1639. test: '123',
  1640. ticket: {
  1641. pending_time: undefined,
  1642. },
  1643. }
  1644. dataLast = {
  1645. test: '123',
  1646. ticket: {
  1647. pending_time: null,
  1648. },
  1649. }
  1650. diff = {}
  1651. result = App.Utils.formDiff(dataNow, dataLast)
  1652. assert.deepEqual(result, diff, 'check form diff')
  1653. dataNow = {
  1654. test: '123',
  1655. }
  1656. dataLast = {}
  1657. diff = {
  1658. test: '123',
  1659. }
  1660. result = App.Utils.formDiff(dataNow, dataLast)
  1661. assert.deepEqual(result, diff, 'check form diff')
  1662. dataNow = {
  1663. test: '123',
  1664. }
  1665. dataLast = {
  1666. test: [1,2,3,4]
  1667. }
  1668. diff = {
  1669. test: '123',
  1670. }
  1671. result = App.Utils.formDiff(dataNow, dataLast)
  1672. assert.deepEqual(result, diff, 'check form diff')
  1673. dataNow = {
  1674. test: '123',
  1675. }
  1676. dataLast = {
  1677. test: {
  1678. 1: 1,
  1679. 2: 2,
  1680. }
  1681. }
  1682. diff = {
  1683. test: '123',
  1684. }
  1685. result = App.Utils.formDiff(dataNow, dataLast)
  1686. assert.deepEqual(result, diff, 'check form diff')
  1687. dataNow = {
  1688. test: [1,2,3,'4']
  1689. }
  1690. dataLast = {
  1691. test: '123',
  1692. }
  1693. diff = {
  1694. test: ['1','2','3','4']
  1695. }
  1696. result = App.Utils.formDiff(dataNow, dataLast)
  1697. assert.deepEqual(result, diff, 'check form diff')
  1698. dataNow = {
  1699. test: {
  1700. 1: 1,
  1701. 2: 2,
  1702. }
  1703. }
  1704. dataLast = {
  1705. test: '123',
  1706. }
  1707. diff = {
  1708. test: {
  1709. 1: '1',
  1710. 2: '2',
  1711. }
  1712. }
  1713. result = App.Utils.formDiff(dataNow, dataLast)
  1714. assert.deepEqual(result, diff, 'check form diff')
  1715. // regression test for issue #2042 - incorrect notification when closing a tab after setting up an object
  1716. // A newly created attribute will have the empty string as its value, this should be ignored for formDiff comparison
  1717. dataNow = {
  1718. test: '',
  1719. }
  1720. dataLast = {}
  1721. diff = {}
  1722. result = App.Utils.formDiff(dataNow, dataLast)
  1723. assert.deepEqual(result, diff, 'check form diff for a newly created attribute that is blank')
  1724. dataNow = {
  1725. test: '',
  1726. }
  1727. dataLast = {
  1728. test: '123',
  1729. }
  1730. diff = {
  1731. test: '',
  1732. }
  1733. result = App.Utils.formDiff(dataNow, dataLast)
  1734. assert.deepEqual(result, diff, 'check form diff for setting a previously valid value to blank')
  1735. dataNow = {
  1736. test: '123',
  1737. ticket: {
  1738. pending_time: undefined,
  1739. },
  1740. }
  1741. dataLast = {
  1742. ticket: {
  1743. pending_time: null,
  1744. },
  1745. }
  1746. diff = {
  1747. test: '123',
  1748. }
  1749. result = App.Utils.formDiff(dataNow, dataLast)
  1750. assert.deepEqual(result, diff, 'check form diff')
  1751. dataNow = undefined
  1752. dataLast = undefined
  1753. diff = {}
  1754. result = App.Utils.formDiff(dataNow, dataLast)
  1755. assert.deepEqual(result, diff, 'check form diff')
  1756. dataNow = {}
  1757. dataLast = {"number":"10012","title":"some subject 123äöü","group_id":1,"owner_id":1,"customer_id":2,"state_id":3,"priority_id":2,"article":{"from":"Test Admin Agent","to":"","cc":"","body":"dasdad","content_type":"text/html","ticket_id":12,"type_id":9,"sender_id":1,"internal":false,"form_id":"523405147"},"updated_at":"2015-01-29T09:22:23.000Z","pending_time":"2015-01-28T22:22:00.000Z","id":12}
  1758. diff = {}
  1759. result = App.Utils.formDiff(dataNow, dataLast)
  1760. assert.deepEqual(result, diff, 'check form diff')
  1761. // do not compare content of data instances/objects
  1762. no = function test_object() {
  1763. this.a = function() { return 123; }
  1764. this.b = function() { return '1234'; }
  1765. this.c = function() { return [123]; }
  1766. this.d = [1,2,3];
  1767. this.e = 'abc';
  1768. }
  1769. no1 = new no()
  1770. no2 = new no()
  1771. no3 = new no()
  1772. dataNow = {
  1773. number:'10013',
  1774. Article: [no1],
  1775. }
  1776. dataLast = {
  1777. number: "10012",
  1778. title: "some subject 123äöü",
  1779. Article: [ no2, no3 ],
  1780. }
  1781. diff = {
  1782. number:'10013',
  1783. }
  1784. result = App.Utils.formDiff(dataNow, dataLast)
  1785. assert.deepEqual(result, diff, 'check form diff')
  1786. dataNow = {
  1787. number:'10013',
  1788. Article: [no1,2],
  1789. }
  1790. dataLast = {
  1791. number: "10012",
  1792. title: "some subject 123äöü",
  1793. Article: [ no2, no3 ],
  1794. }
  1795. diff = {
  1796. number:'10013',
  1797. Article: ['2'],
  1798. }
  1799. result = App.Utils.formDiff(dataNow, dataLast)
  1800. assert.deepEqual(result, diff, 'check form diff')
  1801. dataNow = {
  1802. array: [1,2]
  1803. }
  1804. dataLast = {
  1805. array: [2, 3]
  1806. }
  1807. diff = {
  1808. array: ['1', '3']
  1809. }
  1810. result = App.Utils.formDiff(dataNow, dataLast)
  1811. assert.deepEqual(result, diff, 'check form diff in arrays both ways')
  1812. });
  1813. // check decimal format
  1814. QUnit.test("check decimal format", assert => {
  1815. var string = '123'
  1816. var result = '123.00'
  1817. var verify = App.Utils.decimal(string)
  1818. assert.equal(verify, result, string)
  1819. string = '0.6'
  1820. result = '0.60'
  1821. verify = App.Utils.decimal(string)
  1822. assert.equal(verify, result, string)
  1823. string = '6'
  1824. result = '6.00'
  1825. verify = App.Utils.decimal(string)
  1826. assert.equal(verify, result, string)
  1827. string = 6.5
  1828. result = '6.50'
  1829. verify = App.Utils.decimal(string)
  1830. assert.equal(verify, result, string)
  1831. string = '111111.6'
  1832. result = '111111.60'
  1833. verify = App.Utils.decimal(string)
  1834. assert.equal(verify, result, string)
  1835. string = '111111.622'
  1836. result = '111111.62'
  1837. verify = App.Utils.decimal(string)
  1838. assert.equal(verify, result, string)
  1839. string = 'abc.6'
  1840. result = 'abc.6'
  1841. verify = App.Utils.decimal(string)
  1842. assert.equal(verify, result, string)
  1843. string = ''
  1844. result = ''
  1845. verify = App.Utils.decimal(string)
  1846. assert.equal(verify, result, string)
  1847. string = undefined
  1848. result = ''
  1849. verify = App.Utils.decimal(string)
  1850. assert.equal(verify, result, string)
  1851. string = null
  1852. result = ''
  1853. verify = App.Utils.decimal(string)
  1854. assert.equal(verify, result, string)
  1855. });
  1856. // check formatTime format
  1857. QUnit.test("check formatTime format", assert => {
  1858. var string = '123'
  1859. var result = '123'
  1860. var verify = App.Utils.formatTime(string, 0)
  1861. assert.equal(verify, result, string)
  1862. string = '6'
  1863. result = '06'
  1864. verify = App.Utils.formatTime(string, 2)
  1865. assert.equal(verify, result, string)
  1866. string = ''
  1867. result = '00'
  1868. verify = App.Utils.formatTime(string, 2)
  1869. assert.equal(verify, result, string)
  1870. string = undefined
  1871. result = ''
  1872. verify = App.Utils.formatTime(string, 2)
  1873. assert.equal(verify, result, string)
  1874. string = null
  1875. result = ''
  1876. verify = App.Utils.formatTime(string, 2)
  1877. assert.equal(verify, result, string)
  1878. });
  1879. // check diffPosition
  1880. QUnit.test("check diffPosition format", assert => {
  1881. var a = [1,2,3,4]
  1882. var b = [1,2,3,4,5]
  1883. var result = [
  1884. {
  1885. position: 4,
  1886. id: 5,
  1887. },
  1888. ]
  1889. var verify = App.Utils.diffPositionAdd(a, b)
  1890. assert.deepEqual(verify, result)
  1891. a = [2,3,4]
  1892. b = [1,2,3,4]
  1893. result = [
  1894. {
  1895. position: 0,
  1896. id: 1,
  1897. },
  1898. ]
  1899. verify = App.Utils.diffPositionAdd(a, b)
  1900. assert.deepEqual(verify, result)
  1901. a = [2,3,4]
  1902. b = [1,2,3,4,5]
  1903. result = [
  1904. {
  1905. position: 0,
  1906. id: 1,
  1907. },
  1908. {
  1909. position: 4,
  1910. id: 5,
  1911. },
  1912. ]
  1913. verify = App.Utils.diffPositionAdd(a, b)
  1914. assert.deepEqual(verify, result)
  1915. a = [2,3,4]
  1916. b = [1,99,12,2,3,4,5]
  1917. result = [
  1918. {
  1919. position: 0,
  1920. id: 1,
  1921. },
  1922. {
  1923. position: 1,
  1924. id: 99,
  1925. },
  1926. {
  1927. position: 2,
  1928. id: 12,
  1929. },
  1930. {
  1931. position: 6,
  1932. id: 5,
  1933. },
  1934. ]
  1935. verify = App.Utils.diffPositionAdd(a, b)
  1936. assert.deepEqual(verify, result)
  1937. a = [4,3,1]
  1938. b = [1,2,3,4,5]
  1939. result = false
  1940. verify = App.Utils.diffPositionAdd(a, b)
  1941. assert.deepEqual(verify, result)
  1942. a = ['Ticket-347', 'TicketCreateScreen-2217']
  1943. b = ['Ticket-347', 'TicketCreateScreen-2217', 'TicketCreateScreen-71517']
  1944. result = [
  1945. {
  1946. position: 2,
  1947. id: 'TicketCreateScreen-71517',
  1948. },
  1949. ]
  1950. verify = App.Utils.diffPositionAdd(a, b)
  1951. assert.deepEqual(verify, result)
  1952. });
  1953. // check textLengthWithUrl format
  1954. QUnit.test("check textLengthWithUrl format", assert => {
  1955. var string = '123'
  1956. var result = 3
  1957. var verify = App.Utils.textLengthWithUrl(string)
  1958. assert.equal(verify, result)
  1959. string = '123 http is not here'
  1960. result = 20
  1961. verify = App.Utils.textLengthWithUrl(string)
  1962. assert.equal(verify, result)
  1963. string = '123 http://host is not here'
  1964. result = 39
  1965. verify = App.Utils.textLengthWithUrl(string)
  1966. assert.equal(verify, result)
  1967. string = '123 http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX is not here'
  1968. result = 39
  1969. verify = App.Utils.textLengthWithUrl(string)
  1970. assert.equal(verify, result)
  1971. string = 'http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1972. result = 23
  1973. verify = App.Utils.textLengthWithUrl(string)
  1974. assert.equal(verify, result)
  1975. string = 'http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, some other text'
  1976. result = 23 + 17
  1977. verify = App.Utils.textLengthWithUrl(string)
  1978. assert.equal(verify, result)
  1979. string = 'some other text,http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1980. result = 23 + 16
  1981. verify = App.Utils.textLengthWithUrl(string)
  1982. assert.equal(verify, result)
  1983. string = 'some other text, http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX?abc=123;aaa=ab+c usw'
  1984. result = 23 + 21
  1985. verify = App.Utils.textLengthWithUrl(string)
  1986. assert.equal(verify, result)
  1987. });
  1988. // check getRecipientArticle format
  1989. QUnit.test('check getRecipientArticle format', assert => {
  1990. var customer = {
  1991. login: 'login',
  1992. firstname: 'firstname',
  1993. lastname: 'lastname',
  1994. email: 'customer@example.com',
  1995. }
  1996. var ticket = {
  1997. customer: customer,
  1998. }
  1999. var article = {
  2000. type: {
  2001. name: 'phone',
  2002. },
  2003. sender: {
  2004. name: 'Customer',
  2005. },
  2006. from: customer.email,
  2007. to: 'some group',
  2008. message_id: 'message_id1',
  2009. created_by: {
  2010. login: 'login',
  2011. firstname: 'firstname',
  2012. lastname: 'lastname',
  2013. email: 'article_created_by@example.com',
  2014. },
  2015. }
  2016. var result = {
  2017. to: 'customer@example.com',
  2018. cc: '',
  2019. body: '',
  2020. in_reply_to: 'message_id1',
  2021. }
  2022. var verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2023. assert.deepEqual(verify, result)
  2024. customer = {
  2025. login: 'login',
  2026. firstname: 'firstname',
  2027. lastname: 'lastname',
  2028. email: 'customer@example.com',
  2029. }
  2030. ticket = {
  2031. customer: customer,
  2032. }
  2033. article = {
  2034. type: {
  2035. name: 'phone',
  2036. },
  2037. sender: {
  2038. name: 'Customer',
  2039. },
  2040. from: customer.email,
  2041. message_id: 'message_id2',
  2042. created_by: {
  2043. login: 'login',
  2044. firstname: 'firstname',
  2045. lastname: 'lastname',
  2046. email: 'article_created_by@example.com',
  2047. },
  2048. }
  2049. result = {
  2050. to: customer.email,
  2051. cc: '',
  2052. body: '',
  2053. in_reply_to: 'message_id2',
  2054. }
  2055. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2056. assert.deepEqual(verify, result)
  2057. customer = {
  2058. login: 'login',
  2059. firstname: 'firstname',
  2060. lastname: 'lastname',
  2061. email: 'customer@example.com',
  2062. }
  2063. ticket = {
  2064. customer: customer,
  2065. }
  2066. article = {
  2067. message_id: 'message_id3',
  2068. type: {
  2069. name: 'phone',
  2070. },
  2071. sender: {
  2072. name: 'Agent',
  2073. },
  2074. from: 'article_created_by@example.com',
  2075. created_by: {
  2076. login: 'login',
  2077. firstname: 'firstname',
  2078. lastname: 'lastname',
  2079. email: 'article_created_by@example.com',
  2080. },
  2081. }
  2082. result = {
  2083. to: 'customer@example.com',
  2084. cc: '',
  2085. body: '',
  2086. in_reply_to: 'message_id3',
  2087. }
  2088. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2089. assert.deepEqual(verify, result)
  2090. customer = {
  2091. login: 'login',
  2092. firstname: 'firstname',
  2093. lastname: 'lastname',
  2094. email: 'customer@example.com',
  2095. }
  2096. ticket = {
  2097. customer: customer,
  2098. }
  2099. article = {
  2100. message_id: 'message_id4',
  2101. created_by: customer,
  2102. type: {
  2103. name: 'web',
  2104. },
  2105. sender: {
  2106. name: 'Customer',
  2107. },
  2108. from: customer.email,
  2109. to: 'some group',
  2110. created_by: {
  2111. login: 'login',
  2112. firstname: 'firstname',
  2113. lastname: 'lastname',
  2114. email: 'article_created_by@example.com',
  2115. },
  2116. }
  2117. result = {
  2118. to: 'customer@example.com',
  2119. cc: '',
  2120. body: '',
  2121. in_reply_to: 'message_id4',
  2122. }
  2123. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2124. assert.deepEqual(verify, result)
  2125. customer = {
  2126. login: 'login',
  2127. firstname: 'firstname',
  2128. lastname: 'lastname',
  2129. email: 'customer@example.com',
  2130. }
  2131. ticket = {
  2132. customer: customer,
  2133. }
  2134. article = {
  2135. message_id: 'message_id5',
  2136. type: {
  2137. name: 'web',
  2138. },
  2139. sender: {
  2140. name: 'Customer',
  2141. },
  2142. from: customer.email,
  2143. created_by: {
  2144. login: 'login',
  2145. firstname: 'firstname',
  2146. lastname: 'lastname',
  2147. email: 'article_created_by@example.com',
  2148. }
  2149. }
  2150. result = {
  2151. to: 'customer@example.com',
  2152. cc: '',
  2153. body: '',
  2154. in_reply_to: 'message_id5',
  2155. }
  2156. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2157. assert.deepEqual(verify, result)
  2158. customer = {
  2159. login: 'login',
  2160. firstname: 'firstname',
  2161. lastname: 'lastname',
  2162. email: 'customer@example.com',
  2163. }
  2164. ticket = {
  2165. customer: customer,
  2166. }
  2167. article = {
  2168. message_id: 'message_id6',
  2169. type: {
  2170. name: 'email',
  2171. },
  2172. sender: {
  2173. name: 'Customer',
  2174. },
  2175. from: customer.email,
  2176. to: 'some group',
  2177. created_by: {
  2178. login: 'login',
  2179. firstname: 'firstname',
  2180. lastname: 'lastname',
  2181. email: 'article_created_by@example.com',
  2182. }
  2183. }
  2184. result = {
  2185. to: 'customer@example.com',
  2186. cc: '',
  2187. body: '',
  2188. in_reply_to: 'message_id6',
  2189. }
  2190. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2191. assert.deepEqual(verify, result)
  2192. customer = {
  2193. login: 'login',
  2194. firstname: 'firstname',
  2195. lastname: 'lastname',
  2196. email: 'customer@example.com',
  2197. }
  2198. ticket = {
  2199. customer: customer,
  2200. }
  2201. article = {
  2202. message_id: 'message_id7',
  2203. type: {
  2204. name: 'email',
  2205. },
  2206. sender: {
  2207. name: 'Customer',
  2208. },
  2209. from: 'some other invalid part, ' + customer.email,
  2210. to: 'some group',
  2211. created_by: {
  2212. login: 'login',
  2213. firstname: 'firstname',
  2214. lastname: 'lastname',
  2215. email: 'article_created_by@example.com',
  2216. }
  2217. }
  2218. result = {
  2219. to: 'customer@example.com',
  2220. cc: '',
  2221. body: '',
  2222. in_reply_to: 'message_id7',
  2223. }
  2224. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2225. assert.deepEqual(verify, result)
  2226. customer = {
  2227. login: 'login',
  2228. firstname: 'firstname',
  2229. lastname: 'lastname',
  2230. email: 'customer@example.com',
  2231. }
  2232. ticket = {
  2233. customer: customer,
  2234. }
  2235. article = {
  2236. message_id: 'message_id7.1',
  2237. type: {
  2238. name: 'email',
  2239. },
  2240. sender: {
  2241. name: 'Customer',
  2242. },
  2243. from: 'some other invalid part, Some Realname ' + customer.email,
  2244. to: 'some group',
  2245. created_by: {
  2246. login: 'login',
  2247. firstname: 'firstname',
  2248. lastname: 'lastname',
  2249. email: 'article_created_by@example.com',
  2250. }
  2251. }
  2252. result = {
  2253. to: 'customer@example.com',
  2254. cc: '',
  2255. body: '',
  2256. in_reply_to: 'message_id7.1',
  2257. }
  2258. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2259. console.log(verify)
  2260. assert.deepEqual(verify, result)
  2261. customer = {
  2262. login: 'login',
  2263. firstname: 'firstname',
  2264. lastname: 'lastname',
  2265. email: 'customer@example.com',
  2266. }
  2267. ticket = {
  2268. customer: customer,
  2269. }
  2270. article = {
  2271. message_id: 'message_id7.2',
  2272. type: {
  2273. name: 'email',
  2274. },
  2275. sender: {
  2276. name: 'Customer',
  2277. },
  2278. from: 'some other invalid part, Some Realname ' + customer.email + ' , abc',
  2279. to: 'some group',
  2280. created_by: {
  2281. login: 'login',
  2282. firstname: 'firstname',
  2283. lastname: 'lastname',
  2284. email: 'article_created_by@example.com',
  2285. }
  2286. }
  2287. result = {
  2288. to: 'customer@example.com',
  2289. cc: '',
  2290. body: '',
  2291. in_reply_to: 'message_id7.2',
  2292. }
  2293. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2294. console.log(verify)
  2295. assert.deepEqual(verify, result)
  2296. customer = {
  2297. login: 'login',
  2298. firstname: 'firstname',
  2299. lastname: 'lastname',
  2300. email: 'customer@example.com',
  2301. }
  2302. agent = {
  2303. login: 'login',
  2304. firstname: 'firstname',
  2305. lastname: 'lastname',
  2306. email: 'agent@example.com',
  2307. }
  2308. ticket = {
  2309. customer: customer,
  2310. }
  2311. article = {
  2312. message_id: 'message_id8',
  2313. created_by: agent,
  2314. type: {
  2315. name: 'email',
  2316. },
  2317. sender: {
  2318. name: 'Agent',
  2319. },
  2320. from: 'customer2@example.com',
  2321. to: 'customer@example.com',
  2322. }
  2323. result = {
  2324. to: 'customer2@example.com',
  2325. cc: '',
  2326. body: '',
  2327. in_reply_to: 'message_id8',
  2328. }
  2329. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2330. assert.deepEqual(verify, result)
  2331. customer = {
  2332. login: 'login',
  2333. firstname: 'firstname',
  2334. lastname: 'lastname',
  2335. email: 'customer@example.com',
  2336. }
  2337. agent = {
  2338. login: 'login',
  2339. firstname: 'firstname',
  2340. lastname: 'lastname',
  2341. email: 'agent@example.com',
  2342. }
  2343. ticket = {
  2344. customer: customer,
  2345. }
  2346. article = {
  2347. message_id: 'message_id9',
  2348. created_by: agent,
  2349. type: {
  2350. name: 'email',
  2351. },
  2352. sender: {
  2353. name: 'Agent',
  2354. },
  2355. from: 'agent@example.com',
  2356. to: 'customer@example.com',
  2357. }
  2358. result = {
  2359. to: 'customer@example.com',
  2360. cc: '',
  2361. body: '',
  2362. in_reply_to: 'message_id9',
  2363. }
  2364. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2365. assert.deepEqual(verify, result)
  2366. customer = {
  2367. login: 'login',
  2368. firstname: 'firstname',
  2369. lastname: 'lastname',
  2370. email: 'customer@example.com',
  2371. }
  2372. agent = {
  2373. login: 'login',
  2374. firstname: 'firstname',
  2375. lastname: 'lastname',
  2376. email: 'agent@example.com',
  2377. }
  2378. ticket = {
  2379. customer: customer,
  2380. }
  2381. article = {
  2382. message_id: 'message_id10',
  2383. created_by: agent,
  2384. type: {
  2385. name: 'email',
  2386. },
  2387. sender: {
  2388. name: 'Agent',
  2389. },
  2390. from: 'Agent@Example.com',
  2391. to: 'customer@example.com',
  2392. cc: 'zammad@example.com',
  2393. }
  2394. result = {
  2395. to: 'customer@example.com',
  2396. cc: '',
  2397. body: '',
  2398. in_reply_to: 'message_id10',
  2399. }
  2400. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2401. assert.deepEqual(verify, result)
  2402. customer = {
  2403. login: 'login',
  2404. firstname: 'firstname',
  2405. lastname: 'lastname',
  2406. email: 'customer@example.com',
  2407. }
  2408. agent = {
  2409. login: 'login',
  2410. firstname: 'firstname',
  2411. lastname: 'lastname',
  2412. email: 'agent@example.com',
  2413. }
  2414. ticket = {
  2415. customer: customer,
  2416. }
  2417. article = {
  2418. message_id: 'message_id11',
  2419. created_by: agent,
  2420. type: {
  2421. name: 'email',
  2422. },
  2423. sender: {
  2424. name: 'Agent',
  2425. },
  2426. from: 'Agent@Example.com',
  2427. to: 'customer@example.com, agent@example.com',
  2428. cc: 'zammad@example.com',
  2429. }
  2430. result = {
  2431. to: 'customer@example.com, agent@example.com',
  2432. cc: 'zammad@example.com',
  2433. body: '',
  2434. in_reply_to: 'message_id11',
  2435. }
  2436. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type, [], true)
  2437. assert.deepEqual(verify, result)
  2438. customer = {
  2439. login: 'login',
  2440. firstname: 'firstname',
  2441. lastname: 'lastname',
  2442. email: 'customer@example.com',
  2443. }
  2444. agent = {
  2445. login: 'login',
  2446. firstname: 'firstname',
  2447. lastname: 'lastname',
  2448. email: 'agent@example.com',
  2449. }
  2450. ticket = {
  2451. customer: customer,
  2452. }
  2453. article = {
  2454. message_id: 'message_id12',
  2455. created_by: agent,
  2456. type: {
  2457. name: 'email',
  2458. },
  2459. sender: {
  2460. name: 'Agent',
  2461. },
  2462. from: 'Agent@Example.com',
  2463. to: 'customeR@EXAMPLE.com, agent@example.com',
  2464. cc: 'zammad@example.com, customer@example.com',
  2465. }
  2466. result = {
  2467. to: 'customer@example.com, agent@example.com',
  2468. cc: 'zammad@example.com',
  2469. body: '',
  2470. in_reply_to: 'message_id12',
  2471. }
  2472. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, [], true)
  2473. assert.deepEqual(verify, result)
  2474. customer = {
  2475. login: 'login',
  2476. firstname: 'firstname',
  2477. lastname: 'lastname',
  2478. email: 'customer@example.com',
  2479. }
  2480. agent = {
  2481. login: 'login',
  2482. firstname: 'firstname',
  2483. lastname: 'lastname',
  2484. email: 'agent@example.com',
  2485. }
  2486. ticket = {
  2487. customer: customer,
  2488. }
  2489. article = {
  2490. message_id: 'message_id13',
  2491. created_by: agent,
  2492. type: {
  2493. name: 'email',
  2494. },
  2495. sender: {
  2496. name: 'Agent',
  2497. },
  2498. from: 'Agent@Example.com',
  2499. to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
  2500. cc: 'zammad@example.com, customer2@example.com',
  2501. }
  2502. result = {
  2503. to: 'customer@example.com, agent@example.com',
  2504. cc: 'customer2@example.com',
  2505. body: '',
  2506. in_reply_to: 'message_id13',
  2507. }
  2508. email_addresses = [
  2509. {
  2510. email: 'zammad@example.com',
  2511. },
  2512. {
  2513. email: 'zammad2@example.com',
  2514. }
  2515. ]
  2516. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2517. assert.deepEqual(verify, result)
  2518. customer = {
  2519. login: 'login',
  2520. firstname: 'firstname',
  2521. lastname: 'lastname',
  2522. email: 'customer@example.com',
  2523. }
  2524. agent = {
  2525. login: 'login',
  2526. firstname: 'firstname',
  2527. lastname: 'lastname',
  2528. email: 'AGENT@example.com',
  2529. }
  2530. ticket = {
  2531. customer: customer,
  2532. }
  2533. article = {
  2534. message_id: 'message_id14',
  2535. created_by: agent,
  2536. type: {
  2537. name: 'email',
  2538. },
  2539. sender: {
  2540. name: 'Agent',
  2541. },
  2542. from: 'Agent@Example.com',
  2543. to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
  2544. cc: 'zammad@example.com, customer2@example.com',
  2545. }
  2546. result = {
  2547. to: 'customer@example.com, agent@example.com',
  2548. cc: 'customer2@example.com',
  2549. body: '',
  2550. in_reply_to: 'message_id14',
  2551. }
  2552. email_addresses = [
  2553. {
  2554. email: 'zammad@example.com',
  2555. },
  2556. {
  2557. email: 'zammad2@example.com',
  2558. }
  2559. ]
  2560. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2561. assert.deepEqual(verify, result)
  2562. customer = {
  2563. login: 'login',
  2564. firstname: 'firstname',
  2565. lastname: 'lastname',
  2566. email: 'zammad@example.com',
  2567. }
  2568. ticket = {
  2569. customer: customer,
  2570. }
  2571. article = {
  2572. message_id: 'message_id15',
  2573. created_by: customer,
  2574. type: {
  2575. name: 'email',
  2576. },
  2577. sender: {
  2578. name: 'Agent',
  2579. },
  2580. from: 'zammad@EXAMPLE.com',
  2581. to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
  2582. cc: 'zammad@example.com, customer2@example.com',
  2583. }
  2584. result = {
  2585. to: 'customer@example.com, agent@example.com',
  2586. cc: 'customer2@example.com',
  2587. body: '',
  2588. in_reply_to: 'message_id15',
  2589. }
  2590. email_addresses = [
  2591. {
  2592. email: 'zammad@example.com',
  2593. },
  2594. {
  2595. email: 'zammad2@example.com',
  2596. }
  2597. ]
  2598. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2599. assert.deepEqual(verify, result)
  2600. customer = {
  2601. login: 'login',
  2602. firstname: 'firstname',
  2603. lastname: 'lastname',
  2604. email: 'customer@example.com',
  2605. }
  2606. ticket = {
  2607. customer: customer,
  2608. }
  2609. article = {
  2610. message_id: 'message_id16',
  2611. created_by: customer,
  2612. type: {
  2613. name: 'email',
  2614. },
  2615. sender: {
  2616. name: 'Agent',
  2617. },
  2618. from: 'customer@example.com',
  2619. to: 'customer1@example.com, customer2@example.com, zammad@example.com',
  2620. cc: '',
  2621. }
  2622. result = {
  2623. to: 'customer1@example.com, customer2@example.com, customer@example.com',
  2624. cc: '',
  2625. body: '',
  2626. in_reply_to: 'message_id16',
  2627. }
  2628. email_addresses = [
  2629. {
  2630. email: 'zammad@example.com',
  2631. },
  2632. {
  2633. email: 'zammad2@example.com',
  2634. }
  2635. ]
  2636. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2637. assert.deepEqual(verify, result)
  2638. customer = {
  2639. login: 'login',
  2640. firstname: 'firstname',
  2641. lastname: 'lastname',
  2642. email: 'customer@example.com',
  2643. }
  2644. ticket = {
  2645. customer: customer,
  2646. }
  2647. article = {
  2648. message_id: 'message_id17',
  2649. created_by: customer,
  2650. type: {
  2651. name: 'email',
  2652. },
  2653. sender: {
  2654. name: 'Agent',
  2655. },
  2656. from: 'customer@example.com',
  2657. to: 'customer1@example.com, customer2@example.com, zammad@example.com, customer2+2@example.com',
  2658. cc: '',
  2659. }
  2660. result = {
  2661. to: 'customer1@example.com, customer2@example.com, customer2+2@example.com, customer@example.com',
  2662. cc: '',
  2663. body: '',
  2664. in_reply_to: 'message_id17',
  2665. }
  2666. email_addresses = [
  2667. {
  2668. email: 'zammad@example.com',
  2669. },
  2670. {
  2671. email: 'zammad2@example.com',
  2672. }
  2673. ]
  2674. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2675. assert.deepEqual(verify, result)
  2676. customer = {
  2677. login: 'login',
  2678. firstname: 'firstname',
  2679. lastname: 'lastname',
  2680. email: 'customer@example.com',
  2681. }
  2682. agent = {
  2683. login: 'login',
  2684. firstname: 'firstname',
  2685. lastname: 'lastname',
  2686. email: 'zammad@example.com',
  2687. }
  2688. ticket = {
  2689. customer: customer,
  2690. }
  2691. article = {
  2692. message_id: 'message_id18',
  2693. created_by: agent,
  2694. type: {
  2695. name: 'email',
  2696. },
  2697. sender: {
  2698. name: 'Agent',
  2699. },
  2700. from: 'zammad@example.com',
  2701. to: 'customer@example.com',
  2702. cc: '',
  2703. }
  2704. result = {
  2705. to: 'customer@example.com',
  2706. cc: '',
  2707. body: '',
  2708. in_reply_to: 'message_id18',
  2709. }
  2710. email_addresses = [
  2711. {
  2712. email: 'zammad@example.com',
  2713. },
  2714. {
  2715. email: 'zammad2@example.com',
  2716. }
  2717. ]
  2718. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2719. assert.deepEqual(verify, result)
  2720. customer = {
  2721. login: 'login',
  2722. firstname: 'firstname',
  2723. lastname: 'lastname',
  2724. email: 'customer@example.com',
  2725. }
  2726. agent = {
  2727. login: 'login',
  2728. firstname: 'firstname',
  2729. lastname: 'lastname',
  2730. email: 'zammad@example.com',
  2731. }
  2732. ticket = {
  2733. customer: customer,
  2734. }
  2735. article = {
  2736. message_id: 'message_id19',
  2737. created_by: agent,
  2738. type: {
  2739. name: 'email',
  2740. },
  2741. sender: {
  2742. name: 'Agent',
  2743. },
  2744. from: 'Sender <zammad@example.com>',
  2745. to: 'Customer <customer@example.com>',
  2746. cc: '',
  2747. }
  2748. result = {
  2749. to: 'customer@example.com',
  2750. cc: '',
  2751. body: '',
  2752. in_reply_to: 'message_id19',
  2753. }
  2754. email_addresses = [
  2755. {
  2756. email: 'zammad@example.com',
  2757. },
  2758. {
  2759. email: 'zammad2@example.com',
  2760. }
  2761. ]
  2762. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, false)
  2763. assert.deepEqual(verify, result)
  2764. agent = {
  2765. login: 'login',
  2766. firstname: 'firstname',
  2767. lastname: 'lastname',
  2768. email: 'agent@example.com',
  2769. }
  2770. ticket = {
  2771. customer: agent,
  2772. }
  2773. article = {
  2774. message_id: 'message_id20',
  2775. created_by: agent,
  2776. type: {
  2777. name: 'email',
  2778. },
  2779. sender: {
  2780. name: 'Agent',
  2781. },
  2782. from: 'Agent <Agent@Example.com>',
  2783. to: 'Sender <zammad@example.com>',
  2784. cc: '',
  2785. }
  2786. result = {
  2787. to: 'agent@example.com',
  2788. cc: '',
  2789. body: '',
  2790. in_reply_to: 'message_id20',
  2791. }
  2792. email_addresses = [
  2793. {
  2794. email: 'zammad@example.com',
  2795. },
  2796. {
  2797. email: 'zammad2@example.com',
  2798. }
  2799. ]
  2800. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, false)
  2801. assert.deepEqual(verify, result)
  2802. agent = {
  2803. login: 'login',
  2804. firstname: 'firstname',
  2805. lastname: 'lastname',
  2806. email: 'agent@example.com',
  2807. }
  2808. ticket = {
  2809. customer: agent,
  2810. }
  2811. article = {
  2812. message_id: 'message_id20',
  2813. created_by: agent,
  2814. type: {
  2815. name: 'email',
  2816. },
  2817. sender: {
  2818. name: 'Agent',
  2819. },
  2820. from: 'Agent <Agent@Example.com>',
  2821. to: 'somebodyelse@example.com, Zammad <zammad@example.com>',
  2822. cc: '',
  2823. }
  2824. result = {
  2825. to: 'agent@example.com',
  2826. cc: '',
  2827. body: '',
  2828. in_reply_to: 'message_id20',
  2829. }
  2830. email_addresses = [
  2831. {
  2832. email: 'zammad@example.com',
  2833. },
  2834. {
  2835. email: 'zammad2@example.com',
  2836. }
  2837. ]
  2838. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, false)
  2839. assert.deepEqual(verify, result)
  2840. customer = {
  2841. login: 'login',
  2842. firstname: 'firstname',
  2843. lastname: 'lastname',
  2844. email: "'customer@example.com'",
  2845. }
  2846. agent = {
  2847. login: 'login',
  2848. firstname: 'firstname',
  2849. lastname: 'lastname',
  2850. email: 'agent@example.com',
  2851. }
  2852. ticket = {
  2853. customer: customer,
  2854. }
  2855. article = {
  2856. message_id: 'message_id21',
  2857. created_by: agent,
  2858. type: {
  2859. name: 'email',
  2860. },
  2861. sender: {
  2862. name: 'Agent',
  2863. },
  2864. from: customer.email,
  2865. to: 'agent@example.com',
  2866. }
  2867. result = {
  2868. to: 'customer@example.com',
  2869. cc: '',
  2870. body: '',
  2871. in_reply_to: 'message_id21',
  2872. }
  2873. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2874. assert.deepEqual(verify, result)
  2875. // Regression test for issue #2184
  2876. // Case 1
  2877. // 1. Create a "Received Call" Ticket for article_customer
  2878. // 2. Change the Customer of the ticket to ticket_customer (but article.from still points to article_customer)
  2879. // 3. Reply to the first Article
  2880. // Recipient SHOULD BE Article.from
  2881. var article_customer = {
  2882. login: 'login',
  2883. firstname: 'article',
  2884. lastname: 'lastname',
  2885. email: 'article_customer@example.com',
  2886. }
  2887. var ticket_customer = {
  2888. login: 'login2',
  2889. firstname: 'ticket',
  2890. lastname: 'lastname',
  2891. email: 'ticket_customer@example.com',
  2892. }
  2893. ticket = {
  2894. customer: ticket_customer,
  2895. }
  2896. article = {
  2897. type: {
  2898. name: 'phone',
  2899. },
  2900. sender: {
  2901. name: 'Customer',
  2902. },
  2903. from: 'article lastname <article_customer@example.com>',
  2904. to: 'some group',
  2905. message_id: 'message_id22',
  2906. created_by: {
  2907. login: 'login',
  2908. firstname: 'firstname',
  2909. lastname: 'lastname',
  2910. email: 'article_created_by@example.com',
  2911. },
  2912. }
  2913. result = {
  2914. to: 'article_customer@example.com',
  2915. cc: '',
  2916. body: '',
  2917. in_reply_to: 'message_id22',
  2918. }
  2919. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2920. assert.deepEqual(verify, result)
  2921. // Regression test for issue #2184
  2922. // Case 2
  2923. // 1. Create a "Outbound Call" Ticket for article_customer
  2924. // 2. Change the Customer of the Ticket to ticket_customer (but article.to still points to article_customer)
  2925. // 3. Reply to the first Article
  2926. // Recipient SHOULD BE Article.to
  2927. article_customer = {
  2928. login: 'login',
  2929. firstname: 'article',
  2930. lastname: 'lastname',
  2931. email: 'article_customer@example.com',
  2932. }
  2933. ticket_customer = {
  2934. login: 'login2',
  2935. firstname: 'ticket',
  2936. lastname: 'lastname',
  2937. email: 'ticket_customer@example.com',
  2938. }
  2939. ticket = {
  2940. customer: ticket_customer,
  2941. }
  2942. article = {
  2943. type: {
  2944. name: 'phone',
  2945. },
  2946. sender: {
  2947. name: 'Agent',
  2948. },
  2949. from: 'agent1@example.com',
  2950. to: article_customer.email,
  2951. message_id: 'message_id23',
  2952. created_by: {
  2953. login: 'login',
  2954. firstname: 'firstname',
  2955. lastname: 'lastname',
  2956. email: 'article_created_by@example.com',
  2957. },
  2958. }
  2959. result = {
  2960. to: 'article_customer@example.com',
  2961. cc: '',
  2962. body: '',
  2963. in_reply_to: 'message_id23',
  2964. }
  2965. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2966. assert.deepEqual(verify, result)
  2967. // https://github.com/zammad/zammad/issues/2551
  2968. // If "From:" is local address and "Reply-To:" is available, use it
  2969. var article_customer = {
  2970. login: 'login',
  2971. firstname: 'article',
  2972. lastname: 'lastname',
  2973. email: 'article_customer@example.com',
  2974. }
  2975. var ticket_customer = {
  2976. login: 'login2',
  2977. firstname: 'ticket',
  2978. lastname: 'lastname',
  2979. email: 'ticket_customer@example.com',
  2980. }
  2981. ticket = {
  2982. customer: ticket_customer,
  2983. }
  2984. article = {
  2985. type: {
  2986. name: 'email',
  2987. },
  2988. sender: {
  2989. name: 'Customer',
  2990. },
  2991. from: 'article lastname <article_customer@example.com>',
  2992. to: 'some group',
  2993. reply_to: 'asd@example.com',
  2994. message_id: 'message_id22',
  2995. created_by: {
  2996. login: 'login',
  2997. firstname: 'firstname',
  2998. lastname: 'lastname',
  2999. email: 'article_created_by@example.com',
  3000. },
  3001. }
  3002. email_addresses = [{ email: 'article_customer@example.com'}]
  3003. result = {
  3004. to: 'asd@example.com',
  3005. cc: '',
  3006. body: '',
  3007. in_reply_to: 'message_id22',
  3008. }
  3009. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type, email_addresses)
  3010. assert.deepEqual(verify, result)
  3011. });
  3012. QUnit.test("contentTypeCleanup", assert => {
  3013. var source = "image/png"
  3014. var should = "image/png"
  3015. var result = App.Utils.contentTypeCleanup(source)
  3016. assert.equal(result, should, source)
  3017. source = "image/png; some.file"
  3018. should = "image/png"
  3019. result = App.Utils.contentTypeCleanup(source)
  3020. assert.equal(result, should, source)
  3021. source = "image/png;some.file"
  3022. should = "image/png"
  3023. result = App.Utils.contentTypeCleanup(source)
  3024. assert.equal(result, should, source)
  3025. source = "image/jpeg;some.file"
  3026. should = "image/jpeg"
  3027. result = App.Utils.contentTypeCleanup(source)
  3028. assert.equal(result, should, source)
  3029. source = "image/jpg;some.file"
  3030. should = "image/jpg"
  3031. result = App.Utils.contentTypeCleanup(source)
  3032. assert.equal(result, should, source)
  3033. source = "image/gif;some.file"
  3034. should = "image/gif"
  3035. result = App.Utils.contentTypeCleanup(source)
  3036. assert.equal(result, should, source)
  3037. source = "image/gif\n;some.file"
  3038. should = "image/gif"
  3039. result = App.Utils.contentTypeCleanup(source)
  3040. assert.equal(result, should, source)
  3041. });
  3042. // htmlImage2DataUrl
  3043. QUnit.test("htmlImage2DataUrl", assert => {
  3044. var source = '<div>test 13</div>'
  3045. var should = '<div>test 13</div>'
  3046. var result = App.Utils.htmlImage2DataUrl(source)
  3047. assert.equal(result, should, source)
  3048. source = 'some test'
  3049. should = 'some test'
  3050. result = App.Utils.htmlImage2DataUrl(source)
  3051. assert.equal(result, should, source)
  3052. source = '<img src="some url">some test'
  3053. should = '<img src="data:,">some test'
  3054. result = App.Utils.htmlImage2DataUrl(source)
  3055. assert.equal(result, should, source)
  3056. source = '<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAADAAEDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACv/EABQQAQAAAAAAAAAAAAAAAAAAAAD/xAAUAQEAAAAAAAAAAAAAAAAAAAAF/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AbgQDv//Z">some test'
  3057. should = '<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAADAAEDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACv/EABQQAQAAAAAAAAAAAAAAAAAAAAD/xAAUAQEAAAAAAAAAAAAAAAAAAAAF/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AbgQDv//Z">some test'
  3058. result = App.Utils.htmlImage2DataUrl(source)
  3059. assert.equal(result, should, source)
  3060. source = '<img src="data:image/jpeg;base64,some_data_123">some <img src="some url">test'
  3061. should = '<img src="data:image/jpeg;base64,some_data_123">some <img src="data:,">test'
  3062. result = App.Utils.htmlImage2DataUrl(source)
  3063. assert.equal(result, should, source)
  3064. // GitHub issue #2305
  3065. source = '<img src="cid:1234">some test'
  3066. should = '<img src="cid:1234">some test'
  3067. result = App.Utils.htmlImage2DataUrl(source)
  3068. assert.equal(result, should, source)
  3069. // GitHub issue #2701
  3070. source = '<img alt="foo">some test'
  3071. should = '<img alt="foo">some test'
  3072. result = App.Utils.htmlImage2DataUrl(source)
  3073. assert.equal(result, should, source)
  3074. });
  3075. QUnit.test('App.Utils.icon()', assert => {
  3076. // When given no arguments,
  3077. // expect @icon() to return null
  3078. assert.equal(App.Utils.icon(), null, 'with no arguments')
  3079. // On a modern browser and when given a single argument,
  3080. // expect @icon(name) to return an <svg> tag
  3081. window.svgPolyfill = false
  3082. svgTag = '<svg class="icon icon-foo "><use xlink:href="' + App.Config.get('icons_url') + '#icon-foo" /></svg>'
  3083. assert.equal(App.Utils.icon('foo'), svgTag, 'with one arg / no SVG polyfill')
  3084. // On a modern browser and when given two arguments,
  3085. // expect @icon(name) to return an <svg> tag
  3086. // with second arg as add'l class name
  3087. window.svgPolyfill = false
  3088. svgTag = '<svg class="icon icon-foo bar"><use xlink:href="' + App.Config.get('icons_url') + '#icon-foo" /></svg>'
  3089. assert.equal(App.Utils.icon('foo', 'bar'), svgTag, 'with two args / no SVG polyfill')
  3090. // On a browser requiring SVG polyfill and when given a single argument,
  3091. // expect @icon(name, class) to return an <svg> tag
  3092. // with pathless xlink:href attr
  3093. window.svgPolyfill = true
  3094. svgTag = '<svg class="icon icon-foo "><use xlink:href="#icon-foo" /></svg>'
  3095. assert.equal(App.Utils.icon('foo'), svgTag, 'with one arg / SVG polyfill')
  3096. // On a browser requiring SVG polyfill and when given two arguments,
  3097. // expect @icon(name, class) to return an <svg> tag
  3098. // with pathless xlink:href attr and second arg as add'l class name
  3099. window.svgPolyfill = true
  3100. svgTag = '<svg class="icon icon-foo bar"><use xlink:href="#icon-foo" /></svg>'
  3101. assert.equal(App.Utils.icon('foo', 'bar'), svgTag, 'with two args / SVG polyfill')
  3102. // For a left-to-right browser language and when given an argument containing '{start}' or '{end}',
  3103. // expect @icon(name) to return an <svg> tag
  3104. // replacing '{start}' with 'left' and '{end}' with 'right'
  3105. window.svgPolyfill = false
  3106. App.i18n.dir = function() { return 'ltr' }
  3107. svgTag = '<svg class="icon icon-arrow-left "><use xlink:href="' + App.Config.get('icons_url') + '#icon-arrow-left" /></svg>'
  3108. assert.equal(App.Utils.icon('arrow-{start}'), svgTag, 'for ltr locale / name includes "{start}"')
  3109. svgTag = '<svg class="icon icon-arrow-right "><use xlink:href="' + App.Config.get('icons_url') + '#icon-arrow-right" /></svg>'
  3110. assert.equal(App.Utils.icon('arrow-{end}'), svgTag, 'for ltr locale / name includes "{end}"')
  3111. // For a right-to-left browser language and when given an argument containing '{start}' or '{end}',
  3112. // expect @icon(name) to return an <svg> tag
  3113. // replacing '{start}' with 'left' and '{end}' with 'right'
  3114. window.svgPolyFill = false
  3115. App.i18n.dir = function() { return 'rtl' }
  3116. svgTag = '<svg class="icon icon-arrow-right "><use xlink:href="' + App.Config.get('icons_url') + '#icon-arrow-right" /></svg>'
  3117. assert.equal(App.Utils.icon('arrow-{start}'), svgTag, 'for rtl locale / name includes "{start}"')
  3118. svgTag = '<svg class="icon icon-arrow-left "><use xlink:href="' + App.Config.get('icons_url') + '#icon-arrow-left" /></svg>'
  3119. assert.equal(App.Utils.icon('arrow-{end}'), svgTag, 'for rtl locale / name includes "{end}"')
  3120. });
  3121. var source1 = '<img src="/assets/images/avatar-bg.png">some test'
  3122. $('#image2data1').html(source1)
  3123. var htmlImage2DataUrlTest1 = function() {
  3124. QUnit.test("htmlImage2DataUrl1 async", assert => {
  3125. var result1 = App.Utils.htmlImage2DataUrl(source1)
  3126. assert.ok(result1.match(/some test/), source1)
  3127. assert.ok(!result1.match(/avatar-bg.png/), source1)
  3128. assert.ok(result1.match(/^\<img src=\"data:image\/png;base64,/), source1)
  3129. });
  3130. }
  3131. $('#image2data1 img').one('load', htmlImage2DataUrlTest1)
  3132. var source2 = '<img src="/assets/images/chat-demo-avatar.png">some test'
  3133. $('#image2data2').html(source2)
  3134. var htmlImage2DataUrlTest2Success = function(element) {
  3135. QUnit.test('htmlImage2DataUrl2 async', assert => {
  3136. assert.ok(!$(element).html().match(/chat-demo-avatar/), source2)
  3137. assert.ok($(element).get(0).outerHTML.match(/^\<img src=\"data:image\/png;base64,/), source2)
  3138. assert.ok($(element).attr('style'), 'max-width: 100%;')
  3139. });
  3140. }
  3141. var htmlImage2DataUrlTest2Fail = function() {
  3142. QUnit.test('htmlImage2DataUrl2 async', assert => {
  3143. assert.ok(false, 'fail callback is exectuted!')
  3144. });
  3145. }
  3146. // Gitlab Issue #3538
  3147. // Jpeg images should convert to jpegs
  3148. // This functionality uses alt attribute present in img tag to get file type
  3149. // if alt attribute is missing then it will default to image/png
  3150. var jpegImageSource = '<img src="/assets/images/8000x300.jpg" alt="test.jpeg">jpeg image'
  3151. $('#jpegImage').html(jpegImageSource)
  3152. var htmlImage2DataUrlTest3 = function() {
  3153. QUnit.test("htmlImage2DataUrl3 async", assert => {
  3154. var result = App.Utils.htmlImage2DataUrl(jpegImageSource)
  3155. assert.ok(result.match(/jpeg image/), jpegImageSource)
  3156. assert.ok(result.match(/^\<img src=\"data:image\/jpeg;base64,/), jpegImageSource)
  3157. });
  3158. }
  3159. $('#jpegImage img').one('load', htmlImage2DataUrlTest3)
  3160. var pngImageSource = '<img src="/assets/images/1000x1000.png" alt="test.png">png image'
  3161. $('#pngImage').html(pngImageSource)
  3162. var htmlImage2DataUrlTest4 = function() {
  3163. QUnit.test("htmlImage2DataUrl4 async", assert => {
  3164. var result = App.Utils.htmlImage2DataUrl(pngImageSource)
  3165. assert.ok(result.match(/png image/), pngImageSource)
  3166. assert.ok(result.match(/^\<img src=\"data:image\/png;base64,/), pngImageSource)
  3167. });
  3168. }
  3169. $('#pngImage img').one('load', htmlImage2DataUrlTest4)
  3170. var jpegImageSourceWithoutAlt = '<img src="/assets/images/8000x300.jpg">jpeg image'
  3171. $('#jpegImage2').html(jpegImageSourceWithoutAlt)
  3172. var htmlImage2DataUrlTest5 = function() {
  3173. QUnit.test("htmlImage2DataUrl5 async", assert => {
  3174. var result = App.Utils.htmlImage2DataUrl(jpegImageSourceWithoutAlt)
  3175. assert.ok(result.match(/jpeg image/), jpegImageSourceWithoutAlt)
  3176. assert.ok(result.match(/^\<img src=\"data:image\/png;base64,/), jpegImageSourceWithoutAlt)
  3177. });
  3178. }
  3179. $('#jpegImage2 img').one('load', htmlImage2DataUrlTest5)
  3180. App.Utils.htmlImage2DataUrlAsyncInline($('#image2data2'), {success: htmlImage2DataUrlTest2Success, fail: htmlImage2DataUrlTest2Fail})
  3181. }
  3182. QUnit.test('App.Utils.baseUrl()', assert => {
  3183. configGetBackup = App.Config.get
  3184. // When FQDN is undefined or null,
  3185. // expect @baseUrl() to return window.location.origin
  3186. App.Config.get = function(key) { return undefined }
  3187. assert.equal(App.Utils.baseUrl(), window.location.origin, 'with undefined FQDN')
  3188. App.Config.get = function(key) { return null }
  3189. assert.equal(App.Utils.baseUrl(), window.location.origin, 'with null FQDN')
  3190. // When FQDN is zammad.example.com,
  3191. // expect @baseUrl() to return window.location.origin
  3192. App.Config.get = function(key) {
  3193. if (key === 'fqdn') {
  3194. return 'zammad.example.com'
  3195. }
  3196. }
  3197. assert.equal(App.Utils.baseUrl(), window.location.origin, 'with FQDN zammad.example.com')
  3198. // Otherwise,
  3199. // expect @baseUrl() to return FQDN with current HTTP(S) scheme
  3200. App.Config.get = function(key) {
  3201. if (key === 'fqdn') {
  3202. return 'foo.zammad.com'
  3203. } else if (key === 'http_type') {
  3204. return 'https'
  3205. }
  3206. }
  3207. assert.equal(App.Utils.baseUrl(), 'https://foo.zammad.com', 'with any other FQDN (and https scheme)')
  3208. App.Config.get = function(key) {
  3209. if (key === 'fqdn') {
  3210. return 'bar.zammad.com'
  3211. } else if (key === 'http_type') {
  3212. return 'http'
  3213. }
  3214. }
  3215. assert.equal(App.Utils.baseUrl(), 'http://bar.zammad.com', 'with any other FQDN (and http scheme)')
  3216. App.Config.get = configGetBackup
  3217. });
  3218. QUnit.test('App.Utils.joinUrlComponents()', assert => {
  3219. // When given a list of strings,
  3220. // expect @joinUrlComponents() to join them with slashes
  3221. assert.equal(App.Utils.joinUrlComponents('foo', 'bar', 'baz'), 'foo/bar/baz', 'with a destructured list of strings')
  3222. // When given an array of strings,
  3223. // expect @joinUrlComponents() to join them with slashes
  3224. assert.equal(App.Utils.joinUrlComponents(['foo', 'bar', 'baz']), 'foo/bar/baz', 'with an array of strings')
  3225. // When given a list of many types,
  3226. // expect @joinUrlComponents() to join their string representations with slashes
  3227. assert.equal(App.Utils.joinUrlComponents(0, 1, 'two', true, false, { foo: 'bar' }), '0/1/two/true/false/[object Object]', 'with a list of many types')
  3228. // When given a list including null or undefined,
  3229. // expect @joinUrlComponents() to filter them out of the results before joining the rest with slashes
  3230. assert.equal(App.Utils.joinUrlComponents('foo', undefined, 'bar', null, 'baz'), 'foo/bar/baz', 'with a list including null or undefined')
  3231. });
  3232. QUnit.test('App.Utils.clipboardHtmlIsWithText()', assert => {
  3233. // no content with text
  3234. assert.equal(App.Utils.clipboardHtmlIsWithText('<div></div>'), false)
  3235. assert.equal(App.Utils.clipboardHtmlIsWithText('<div> </div>'), false)
  3236. assert.equal(App.Utils.clipboardHtmlIsWithText('<div><img src="test.jpg"/></div>'), false)
  3237. assert.equal(App.Utils.clipboardHtmlIsWithText('<div><!-- some comment --></div>'), false)
  3238. assert.equal(App.Utils.clipboardHtmlIsWithText('<div><!-- some comment --> </div>'), false)
  3239. assert.equal(App.Utils.clipboardHtmlIsWithText("<div><!-- some comment --> \n </div>"), false)
  3240. // content with text
  3241. assert.equal(App.Utils.clipboardHtmlIsWithText('test'), true)
  3242. assert.equal(App.Utils.clipboardHtmlIsWithText('<div>test</div>'), true)
  3243. assert.equal(App.Utils.clipboardHtmlIsWithText('<meta http-equiv="content-type" content="text/html; charset=utf-8">sometext'), true)
  3244. });
  3245. QUnit.test('App.Utils.clipboardHtmlInsertPreperation()', assert => {
  3246. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div></div>', {}), '')
  3247. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div> </div>', {}), ' ')
  3248. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><img src="test.jpg"/></div>', {}), '<img src="test.jpg">')
  3249. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><!-- some comment --></div>', {}), '')
  3250. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><!-- some comment --> </div>', {}), ' ')
  3251. assert.equal(App.Utils.clipboardHtmlInsertPreperation("<div><!-- some comment --> \n </div>", {}), " \n ")
  3252. assert.equal(App.Utils.clipboardHtmlInsertPreperation('test', {}), 'test')
  3253. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div>test</div>', {}), 'test')
  3254. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<meta http-equiv="content-type" content="text/html; charset=utf-8">sometext', {}), '<span>sometext</span>')
  3255. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><b>test</b> 123</div>', { mode: 'textonly' }), 'test 123')
  3256. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><b>test</b><br> 123</div>', { mode: 'textonly' }), 'test 123')
  3257. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><b>test</b><br> 123</div>', { mode: 'textonly', multiline: true }), 'test<br> 123')
  3258. });
  3259. QUnit.test('App.Utils.signatureIdentifyByHtmlHelper()', assert => {
  3260. result = App.Utils.signatureIdentifyByHtmlHelper("&lt;script&gt;alert('fish2');&lt;/script&gt;<blockquote></blockquote>")
  3261. assert.equal(result, "&lt;script&gt;alert('fish2');&lt;/script&gt;<span class=\"js-signatureMarker\"></span><blockquote></blockquote>", 'signatureIdentifyByHtmlHelper does not reactivate alert')
  3262. });
  3263. QUnit.test("#safeParseHtml", assert => {
  3264. var unwrap = input => $('<div>').html(input)[0].innerHTML
  3265. var html = "<div>test 123 </div>"
  3266. var result = App.Utils.safeParseHtml(html)
  3267. var should = html
  3268. assert.equal(unwrap(result), html)
  3269. // test if, according to jQuery, invalid HTML does not cause a a crash
  3270. // https://github.com/zammad/zammad/issues/3393
  3271. html = "<td></td><table></table><div>test 123 </div>"
  3272. should = "<table></table><div>test 123 </div>"
  3273. result = App.Utils.safeParseHtml(html)
  3274. assert.equal(unwrap(result), should)
  3275. })
  3276. QUnit.test("#buildEmailAddress", assert => {
  3277. assert.equal(
  3278. App.Utils.buildEmailAddress(undefined, 'undef@example.com'),
  3279. 'undef@example.com'
  3280. )
  3281. assert.equal(
  3282. App.Utils.buildEmailAddress(null, 'null@example.com'),
  3283. 'null@example.com'
  3284. )
  3285. assert.equal(
  3286. App.Utils.buildEmailAddress('', 'nobody@example.com'),
  3287. 'nobody@example.com'
  3288. )
  3289. assert.equal(
  3290. App.Utils.buildEmailAddress('John Doe', 'john.doe@example.com'),
  3291. 'John Doe <john.doe@example.com>'
  3292. )
  3293. assert.equal(
  3294. App.Utils.buildEmailAddress('Somebody @ "Company"', 'some.body@example.com'),
  3295. '"Somebody @ \\"Company\\"" <some.body@example.com>'
  3296. )
  3297. })