html_utils.js 173 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519
  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 = "<div>Some &nbsp; Value 123</div>"
  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 = 'test@example.com some text'
  237. result = App.Utils.linkify(source)
  238. assert.equal(result, should, source)
  239. source = "abc test@example.com some text"
  240. should = 'abc test@example.com 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=\"assets/images/icons.svg#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/assets/images/icons.svg#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=\"assets/images/icons.svg#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=\"assets/images/icons.svg#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/assets/images/icons.svg#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. });
  573. // wrap
  574. QUnit.test("wrap", assert => {
  575. var source = "some text"
  576. var should = 'some text'
  577. var result = App.Utils.wrap(source)
  578. assert.equal(result, should, source)
  579. source = "some text\nsome other text\n"
  580. should = "some text\nsome other text\n"
  581. result = App.Utils.wrap(source)
  582. assert.equal(result, should, source)
  583. source = "some text with some line to wrap"
  584. should = "some text with\nsome line to\nwrap"
  585. result = App.Utils.wrap(source, 14)
  586. assert.equal(result, should, source)
  587. source = "some text\nsome other text\n"
  588. should = "some text\nsome other text\n"
  589. result = App.Utils.wrap(source)
  590. assert.equal(result, should, source)
  591. source = "1234567890 1234567890 1234567890 1234567890"
  592. should = "1234567890 1234567890 1234567890 1234567890"
  593. result = App.Utils.wrap(source)
  594. assert.equal(result, should, source)
  595. source = "123456789012 123456789012 123456789012"
  596. should = "123456789012\n123456789012\n123456789012"
  597. result = App.Utils.wrap(source, 14)
  598. assert.equal(result, should, source)
  599. });
  600. // remove empty lines
  601. QUnit.test("remove empty lines", assert => {
  602. var source = "\ntest 123\n"
  603. var should = "test 123\n"
  604. var result = App.Utils.removeEmptyLines(source)
  605. assert.equal(result, should, source)
  606. source = "\ntest\n\n123\n"
  607. should = "test\n123\n"
  608. result = App.Utils.removeEmptyLines(source)
  609. assert.equal(result, should, source)
  610. });
  611. // quote
  612. QUnit.test("quote", assert => {
  613. var source = "some text"
  614. var should = '> some text'
  615. var result = App.Utils.quote(source)
  616. assert.equal(result, should, source)
  617. source = "some text\nsome other text\n"
  618. should = "> some text\n> some other text"
  619. result = App.Utils.quote(source)
  620. assert.equal(result, should, source)
  621. source = "\n\nsome text\nsome other text\n \n"
  622. should = "> some text\n> some other text"
  623. result = App.Utils.quote(source)
  624. assert.equal(result, should, source)
  625. source = "Welcome!\n\nThank you for installing Zammad.\n\nYou will find ..."
  626. should = "> Welcome!\n>\n> Thank you for installing Zammad.\n>\n> You will find ..."
  627. result = App.Utils.quote(source)
  628. assert.equal(result, should, source)
  629. source = "Welcome! Thank you for installing Zammad. You will find ..."
  630. should = "> Welcome! Thank you\n> for installing\n> Zammad. You will\n> find ..."
  631. result = App.Utils.quote(source, 20)
  632. assert.equal(result, should, source)
  633. });
  634. // check signature
  635. QUnit.test("check signature", assert => {
  636. var message = "<div>test 123 </div>"
  637. var signature = '<div>--<br>Some Signature<br>some department</div>'
  638. var result = App.Utils.signatureCheck(message, signature)
  639. assert.equal(result, true)
  640. message = "<div>test 123 <div>--<br>Some Signature<br>some department\n</div></div>"
  641. signature = '<div>--<br>Some Signature<br>some department</div>'
  642. result = App.Utils.signatureCheck(message, signature)
  643. assert.equal(result, false)
  644. message = "<div>test 123 <div>--<br>Some Signature\n<br>some department\n</div></div>"
  645. signature = '<div>--<br>Some Signature<br>some department</div>'
  646. result = App.Utils.signatureCheck(message, signature)
  647. assert.equal(result, false)
  648. message = "<div>test 123 <div>--<p>Some Signature</p>\n<p><div>some department</div>\n</p>\n</div></div>"
  649. signature = '<div>--<br>Some Signature<br>some department</div>'
  650. result = App.Utils.signatureCheck(message, signature)
  651. assert.equal(result, false)
  652. message = ""
  653. signature = '<div>--<br>Some Signature<br>some department</div>'
  654. result = App.Utils.signatureCheck(message, signature)
  655. assert.equal(result, true)
  656. message = ""
  657. signature = "--\nSome Signature\nsome department"
  658. result = App.Utils.signatureCheck(message, signature)
  659. assert.equal(result, true)
  660. });
  661. // identify signature
  662. QUnit.test("identify signature by plaintext", assert => {
  663. var message = "<div>test 123 </div>"
  664. var should = '<div>test 123 </div>'
  665. var result = App.Utils.signatureIdentifyByPlaintext(message)
  666. assert.equal(result, should)
  667. message = "<div>test 123 <br/>--<br/>Bob Smith</div>"
  668. should = '<div>test 123 <br/>--<br/>Bob Smith</div>'
  669. result = App.Utils.signatureIdentifyByPlaintext(message)
  670. assert.equal(result, should)
  671. 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>"
  672. 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>'
  673. result = App.Utils.signatureIdentifyByPlaintext(message)
  674. assert.equal(result, should)
  675. message = "<div>test 123 <br/><br/>--no not match--<br/>--<br/>Bob Smith</div>"
  676. should = '<div>test 123 <br/><br/>--no not match--<br/><span class="js-signatureMarker"></span>--<br/>Bob Smith</div>'
  677. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  678. assert.equal(result, should)
  679. message = "<div>test 123 <br/><br/>--no not match--<br/> -- <br/>Bob Smith</div>"
  680. should = '<div>test 123 <br/><br/>--no not match--<br/><span class="js-signatureMarker"></span> -- <br/>Bob Smith</div>'
  681. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  682. assert.equal(result, should)
  683. message = "<div>test 123 <br/><br/>--<br/>Bob Smith<br/><br/><br/><br/><br/>--<br/>Bob Smith</div>"
  684. should = '<div>test 123 <br/><br/><span class="js-signatureMarker"></span>--<br/>Bob Smith<br/><br/><br/><br/><br/>--<br/>Bob Smith</div>'
  685. //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>'
  686. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  687. assert.equal(result, should)
  688. message = "<div>test 123</div><div>test 123</div><div>--</div><div>Bob Smith</div>"
  689. should = "<div>test 123</div><div>test 123</div><div><span class=\"js-signatureMarker\"></span>--</div><div>Bob Smith</div>"
  690. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  691. assert.equal(result, should)
  692. 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>"
  693. 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>"
  694. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  695. assert.equal(result, should)
  696. 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"
  697. 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"
  698. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  699. assert.equal(result, should)
  700. message = "<br>&lt; On 20 Oct 2016, at 12:23, Martin Edenhofer via Zammad Helpdesk wrote:<br>"
  701. should = "<br><span class=\"js-signatureMarker\"></span>&lt; On 20 Oct 2016, at 12:23, Martin Edenhofer via Zammad Helpdesk wrote:<br>"
  702. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  703. assert.equal(result, should)
  704. // apple
  705. // en
  706. 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>"
  707. 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>'
  708. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  709. assert.equal(result, should)
  710. // de
  711. 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>"
  712. 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>'
  713. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  714. assert.equal(result, should)
  715. // ms
  716. // en
  717. 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>"
  718. 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>'
  719. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  720. assert.equal(result, should)
  721. 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>"
  722. 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>'
  723. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  724. assert.equal(result, should)
  725. 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>"
  726. 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>'
  727. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  728. assert.equal(result, should)
  729. // de
  730. 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>"
  731. 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>'
  732. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  733. assert.equal(result, should)
  734. 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>"
  735. 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>"
  736. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  737. assert.equal(result, should)
  738. 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>"
  739. 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>"
  740. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  741. assert.equal(result, should)
  742. 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>"
  743. 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>"
  744. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  745. assert.equal(result, should)
  746. 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>"
  747. 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>"
  748. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  749. assert.equal(result, should)
  750. 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>"
  751. 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>"
  752. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  753. assert.equal(result, should)
  754. 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>"
  755. 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>"
  756. result = App.Utils.signatureIdentifyByPlaintext(message, true, true)
  757. assert.equal(result, should)
  758. 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>"
  759. 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>"
  760. result = App.Utils.signatureIdentifyByPlaintext(message, true, true)
  761. assert.equal(result, should)
  762. 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>"
  763. 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>"
  764. result = App.Utils.signatureIdentifyByPlaintext(message, false, true)
  765. assert.equal(result, should)
  766. // fr
  767. 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>"
  768. 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>'
  769. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  770. assert.equal(result, should)
  771. // thunderbird
  772. // de
  773. 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>"
  774. 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>"
  775. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  776. assert.equal(result, should)
  777. // en - Thunderbird default - http://kb.mozillazine.org/Reply_header_settings
  778. 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>"
  779. 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>"
  780. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  781. assert.equal(result, should)
  782. // en - http://kb.mozillazine.org/Reply_header_settings
  783. 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>"
  784. 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>"
  785. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  786. assert.equal(result, should)
  787. // otrs
  788. // en
  789. 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>"
  790. 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>'
  791. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  792. assert.equal(result, should)
  793. // de
  794. 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>"
  795. 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>'
  796. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  797. assert.equal(result, should)
  798. message = "<div>test 123 <br/><br/></div><div>24.02.2015 14:20 - Roy Kaldung via Zammad Sales schrieb: &nbsp;</div>"
  799. 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>"
  800. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  801. assert.equal(result, should)
  802. // zammad
  803. 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>"
  804. 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>"
  805. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  806. assert.equal(result, should)
  807. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><blockquote type=\"cite\">lalala</blockquote></div>"
  808. 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>"
  809. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  810. assert.equal(result, should)
  811. // gmail
  812. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><blockquote class=\"ecxgmail_quote\">lalala</blockquote></div>"
  813. 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>"
  814. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  815. assert.equal(result, should)
  816. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/><blockquote class=\"gmail_quote\">lalala</blockquote></div>"
  817. 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>"
  818. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  819. assert.equal(result, should)
  820. 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>"
  821. 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>"
  822. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  823. assert.equal(result, should)
  824. // word 14
  825. // en
  826. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>Bob Smith wrote:<br/>lalala</div>"
  827. 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>'
  828. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  829. assert.equal(result, should)
  830. // de
  831. message = "<div>test 123 <br/><br/>--no not match--<br/><br/>Bob Smith<br/>Bob Smith schrieb:<br/>lalala</div>"
  832. 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>'
  833. result = App.Utils.signatureIdentifyByPlaintext(message, true)
  834. assert.equal(result, should)
  835. });
  836. QUnit.test("identify signature by HTML", assert => {
  837. var message = "<div>test 123 </div>"
  838. var should = message
  839. var result = App.Utils.signatureIdentifyByHtml(message)
  840. assert.equal(result, should)
  841. // test if, according to jQuery, invalid HTML does not cause a a crash
  842. // https://github.com/zammad/zammad/issues/3393
  843. message = "<td></td><table></table><div>test 123 </div>"
  844. should = message
  845. result = App.Utils.signatureIdentifyByHtml(message)
  846. assert.equal(result, should)
  847. // simple case 1
  848. message = '<div>actual content</div><blockquote>quoted content</blockquote>'
  849. should = '<div>actual content</div><span class="js-signatureMarker"></span><blockquote>quoted content</blockquote>'
  850. result = App.Utils.signatureIdentifyByHtml(message)
  851. assert.equal(result, should)
  852. // simple case 2
  853. message = '<div>actual content</div><blockquote>quoted content</blockquote><br><div><br></div><div><br> </div>'
  854. should = '<div>actual content</div><span class="js-signatureMarker"></span><blockquote>quoted content</blockquote><br><div><br></div><div><br> </div>'
  855. result = App.Utils.signatureIdentifyByHtml(message)
  856. assert.equal(result, should)
  857. // simple case 3
  858. message = '<div>actual content</div><blockquote>quoted content</blockquote><br><div>actual content 2</div>'
  859. should = message
  860. result = App.Utils.signatureIdentifyByHtml(message)
  861. assert.equal(result, should)
  862. // simple case 4
  863. message = ' content 0 <div>content 1</div> content 2 <blockquote>quoted content</blockquote><br><div><br></div><div><br> </div>'
  864. 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>'
  865. result = App.Utils.signatureIdentifyByHtml(message)
  866. assert.equal(result, should)
  867. // Invalid html signature detection for exchange warning boxes #3571
  868. 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>'
  869. 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>'
  870. result = App.Utils.signatureIdentifyByHtml(message)
  871. assert.equal(result, should)
  872. // Invalid html signature detection for exchange warning boxes #3571
  873. 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>'
  874. 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>'
  875. result = App.Utils.signatureIdentifyByHtml(message)
  876. assert.equal(result, should)
  877. // Gmail via Safari on MacOS 10.12
  878. message = '<div dir="ltr">Reply with <b>gmail</b> via Safari on MacOS 10.12</div><br>\
  879. <div>\
  880. <div dir="ltr">Am Mi., 5. Sep. 2018 um 09:22 Uhr schrieb Billy Zhou &lt;bz@zammad.com&gt;:<br>\
  881. </div>\
  882. <blockquote>test email content<br>\
  883. <br>\
  884. </blockquote>\
  885. </div>'
  886. should = '<div dir="ltr">Reply with <b>gmail</b> via Safari on MacOS 10.12</div><br>\
  887. <span class=\"js-signatureMarker\"></span><div>\
  888. <div dir="ltr">Am Mi., 5. Sep. 2018 um 09:22 Uhr schrieb Billy Zhou &lt;bz@zammad.com&gt;:<br>\
  889. </div>\
  890. <blockquote>test email content<br>\
  891. <br>\
  892. </blockquote>\
  893. </div>'
  894. result = App.Utils.signatureIdentifyByHtml(message)
  895. assert.equal(result, should)
  896. // Yahoo Mail via Safari on MacOS 10.12
  897. 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>'
  898. 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>'
  899. result = App.Utils.signatureIdentifyByHtml(message)
  900. assert.equal(result, should)
  901. // Thunderbird 52 on MacOS 10.12
  902. message = 'Reply with <b>Thunderbird 52</b> on MacOS 10.12<br>\
  903. <br>\
  904. <div class="moz-cite-prefix">Am 04.09.18 um 15:32 schrieb Billy\
  905. Zhou:<br>\
  906. </div>\
  907. <blockquote type="cite"\
  908. cite="mid:da18ed01-b187-a383-bfe7-72663cf82a83@zammad.com">test\
  909. email content\
  910. <br>\
  911. <br>\
  912. </blockquote>\
  913. <br>'
  914. should = 'Reply with <b>Thunderbird 52</b> on MacOS 10.12<br>\
  915. <br>\
  916. <div class="moz-cite-prefix">Am 04.09.18 um 15:32 schrieb Billy\
  917. Zhou:<br>\
  918. </div>\
  919. <span class=\"js-signatureMarker\"></span><blockquote type="cite" cite="mid:da18ed01-b187-a383-bfe7-72663cf82a83@zammad.com">test\
  920. email content\
  921. <br>\
  922. <br>\
  923. </blockquote>\
  924. <br>'
  925. result = App.Utils.signatureIdentifyByHtml(message)
  926. assert.equal(result, should)
  927. // Apple Mail on MacOS 10
  928. 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="">'
  929. 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="">'
  930. result = App.Utils.signatureIdentifyByHtml(message)
  931. assert.equal(result, should)
  932. // Office 365 (10325.20118) on Windows 10 Build 1803
  933. // With German marker: -----Ursprüngliche Nachricht-----
  934. // Using fallback to signatureIdentifyByPlaintext
  935. message = '<div>\
  936. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  937. <p> </p>\
  938. <p><b>fett</b></p>\
  939. <p> </p>\
  940. <span class="js-signatureMarker"></span><p>--</p>\
  941. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  942. <p> </p>\
  943. <p>P: +49 (0) 30 55 57 160-0</p>\
  944. <p>F: +49 (0) 30 55 57 160-99</p>\
  945. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  946. <p> </p>\
  947. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  948. <p>Managing Director: Martin Edenhofer</p>\
  949. <p> </p>\
  950. <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>\
  951. <p> </p>\
  952. <p>test email content</p>\
  953. <p> </p>\
  954. </div>'
  955. should = '<div>\
  956. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  957. <p> </p>\
  958. <p><b>fett</b></p>\
  959. <p> </p>\
  960. <span class="js-signatureMarker"></span><p><span class=\"js-signatureMarker\"></span>--</p>\
  961. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  962. <p> </p>\
  963. <p>P: +49 (0) 30 55 57 160-0</p>\
  964. <p>F: +49 (0) 30 55 57 160-99</p>\
  965. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  966. <p> </p>\
  967. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  968. <p>Managing Director: Martin Edenhofer</p>\
  969. <p> </p>\
  970. <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>\
  971. <p> </p>\
  972. <p>test email content</p>\
  973. <p> </p>\
  974. </div>'
  975. result = App.Utils.signatureIdentifyByHtml(message)
  976. assert.equal(result, should)
  977. // Office 365 (10325.20118) on Windows 10 Build 1803
  978. // With English marker: -----Original Message-----
  979. // Using fallback to signatureIdentifyByPlaintext
  980. message = '<div>\
  981. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  982. <p> </p>\
  983. <p><b>fett</b></p>\
  984. <p> </p>\
  985. <span class="js-signatureMarker"></span><p>--</p>\
  986. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  987. <p> </p>\
  988. <p>P: +49 (0) 30 55 57 160-0</p>\
  989. <p>F: +49 (0) 30 55 57 160-99</p>\
  990. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  991. <p> </p>\
  992. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  993. <p>Managing Director: Martin Edenhofer</p>\
  994. <p> </p>\
  995. <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>\
  996. <p> </p>\
  997. <p>test email content</p>\
  998. <p> </p>\
  999. </div>'
  1000. should = '<div>\
  1001. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  1002. <p> </p>\
  1003. <p><b>fett</b></p>\
  1004. <p> </p>\
  1005. <span class="js-signatureMarker"></span><p><span class=\"js-signatureMarker\"></span>--</p>\
  1006. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  1007. <p> </p>\
  1008. <p>P: +49 (0) 30 55 57 160-0</p>\
  1009. <p>F: +49 (0) 30 55 57 160-99</p>\
  1010. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  1011. <p> </p>\
  1012. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  1013. <p>Managing Director: Martin Edenhofer</p>\
  1014. <p> </p>\
  1015. <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>\
  1016. <p> </p>\
  1017. <p>test email content</p>\
  1018. <p> </p>\
  1019. </div>'
  1020. result = App.Utils.signatureIdentifyByHtml(message)
  1021. assert.equal(result, should)
  1022. // Office 365 (10325.20118) on Windows 10 Build 1803
  1023. // With German marker: -----Ursprüngliche Nachricht-----
  1024. // Without any existing <span class="js-signatureMarker"></span>
  1025. // Using fallback to signatureIdentifyByPlaintext
  1026. message = '<div>\
  1027. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  1028. <p> </p>\
  1029. <p><b>fett</b></p>\
  1030. <p> </p>\
  1031. <p>--</p>\
  1032. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  1033. <p> </p>\
  1034. <p>P: +49 (0) 30 55 57 160-0</p>\
  1035. <p>F: +49 (0) 30 55 57 160-99</p>\
  1036. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  1037. <p> </p>\
  1038. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  1039. <p>Managing Director: Martin Edenhofer</p>\
  1040. <p> </p>\
  1041. <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>\
  1042. <p> </p>\
  1043. <p>test email content</p>\
  1044. <p> </p>\
  1045. </div>'
  1046. should = '<div>\
  1047. <p>Reply with Office 365 (10325.20118) on Windows 10 Build 1803</p>\
  1048. <p> </p>\
  1049. <p><b>fett</b></p>\
  1050. <p> </p>\
  1051. <p><span class=\"js-signatureMarker\"></span>--</p>\
  1052. <p>Zammad GmbH // Marienstraße 11 // 10117 Berlin // Germany</p>\
  1053. <p> </p>\
  1054. <p>P: +49 (0) 30 55 57 160-0</p>\
  1055. <p>F: +49 (0) 30 55 57 160-99</p>\
  1056. <p>W: <a href="https://zammad.com" rel="nofollow noreferrer noopener" target="_blank">https://zammad.com</a></p>\
  1057. <p> </p>\
  1058. <p>Location: Berlin - HRB 163946 B Amtsgericht Berlin-Charlottenburg</p>\
  1059. <p>Managing Director: Martin Edenhofer</p>\
  1060. <p> </p>\
  1061. <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>\
  1062. <p> </p>\
  1063. <p>test email content</p>\
  1064. <p> </p>\
  1065. </div>'
  1066. result = App.Utils.signatureIdentifyByHtml(message)
  1067. assert.equal(result, should)
  1068. });
  1069. // check attachment references
  1070. QUnit.test("check check attachment reference", assert => {
  1071. var message = 'some not existing'
  1072. var result = false
  1073. var verify = App.Utils.checkAttachmentReference(message)
  1074. assert.equal(verify, result)
  1075. message = 'some attachment for you'
  1076. result = 'Attachment'
  1077. verify = App.Utils.checkAttachmentReference(message)
  1078. assert.equal(verify, result)
  1079. message = 'your attachment.'
  1080. result = 'Attachment'
  1081. verify = App.Utils.checkAttachmentReference(message)
  1082. assert.equal(verify, result)
  1083. message = 'some otherattachment for you'
  1084. result = false
  1085. verify = App.Utils.checkAttachmentReference(message)
  1086. assert.equal(verify, result)
  1087. message = 'some attachmentother for you'
  1088. result = false
  1089. verify = App.Utils.checkAttachmentReference(message)
  1090. assert.equal(verify, result)
  1091. message = 'someattachment'
  1092. result = false
  1093. verify = App.Utils.checkAttachmentReference(message)
  1094. assert.equal(verify, result)
  1095. message = 'As enclosed you will find.'
  1096. result = 'Enclosed'
  1097. verify = App.Utils.checkAttachmentReference(message)
  1098. assert.equal(verify, result)
  1099. 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>'
  1100. result = false
  1101. verify = App.Utils.checkAttachmentReference(message)
  1102. assert.equal(verify, result)
  1103. message = '<div>Hi Test,</div><div><blockquote type="cite">cite attachment </blockquote></div>'
  1104. result = false
  1105. verify = App.Utils.checkAttachmentReference(message)
  1106. assert.equal(verify, result)
  1107. message = '<div>Hi Test,</div><div><blockquote class="ecxgmail_quote">ecxgmail_quote attachment </blockquote></div>'
  1108. result = false
  1109. verify = App.Utils.checkAttachmentReference(message)
  1110. assert.equal(verify, result)
  1111. });
  1112. // replace tags
  1113. QUnit.test("check replace tags", assert => {
  1114. var formatNumber = function(num, digits) {
  1115. while (num.toString().length < digits) {
  1116. num = '0' + num
  1117. }
  1118. return num
  1119. }
  1120. var formatTimestamp = function(timestamp) {
  1121. localTime = new Date(Date.parse(timestamp))
  1122. d = formatNumber(localTime.getDate(), 2)
  1123. m = formatNumber(localTime.getMonth() + 1, 2)
  1124. yfull = localTime.getFullYear()
  1125. M = formatNumber(localTime.getMinutes(), 2)
  1126. H = formatNumber(localTime.getHours(), 2)
  1127. l = (H + 11) % 12 + 1
  1128. if (l < 10) {
  1129. l = ' ' + l
  1130. }
  1131. P = H >= 12 ? 'pm' : 'am'
  1132. return m + '/' + d + '/' + yfull + ' ' + l + ':' + M + ' ' + P
  1133. }
  1134. var message = "<div>#{user.firstname} #{user.lastname}</div>"
  1135. var result = '<div>Bob Smith</div>'
  1136. var data = {
  1137. user: {
  1138. firstname: 'Bob',
  1139. lastname: 'Smith',
  1140. },
  1141. }
  1142. var verify = App.Utils.replaceTags(message, data)
  1143. assert.equal(verify, result)
  1144. message = "<div>#{user.firstname} #{user.lastname}</div>"
  1145. result = '<div>Bob Smith</div>'
  1146. data = {
  1147. user: {
  1148. firstname: function() { return 'Bob' },
  1149. lastname: function() { return 'Smith' },
  1150. },
  1151. }
  1152. verify = App.Utils.replaceTags(message, data)
  1153. assert.equal(verify, result)
  1154. message = "<div>#{user.firstname} #{user.lastname}</div>"
  1155. result = '<div>Bob -</div>'
  1156. data = {
  1157. user: {
  1158. firstname: 'Bob',
  1159. },
  1160. }
  1161. verify = App.Utils.replaceTags(message, data)
  1162. assert.equal(verify, result)
  1163. message = "<div>#{user.firstname} #{user.lastname}</div>"
  1164. result = '<div>Bob 0</div>'
  1165. data = {
  1166. user: {
  1167. firstname: 'Bob',
  1168. lastname: 0,
  1169. },
  1170. }
  1171. verify = App.Utils.replaceTags(message, data)
  1172. assert.equal(verify, result)
  1173. message = "<div>#{user.firstname} #{user.lastname}</div>"
  1174. result = '<div>Bob -</div>'
  1175. data = {
  1176. user: {
  1177. firstname: 'Bob',
  1178. lastname: '',
  1179. },
  1180. }
  1181. verify = App.Utils.replaceTags(message, data)
  1182. assert.equal(verify, result)
  1183. message = "<div>#{user.firstname} #{user.not.existing.test}</div>"
  1184. result = '<div>Bob -</div>'
  1185. data = {
  1186. user: {
  1187. firstname: 'Bob',
  1188. },
  1189. }
  1190. verify = App.Utils.replaceTags(message, data)
  1191. assert.equal(verify, result)
  1192. message = "<div>#{user.firstname} #{not.existing.test}</div>"
  1193. result = '<div>Bob -</div>'
  1194. data = {
  1195. user: {
  1196. firstname: 'Bob',
  1197. },
  1198. }
  1199. verify = App.Utils.replaceTags(message, data)
  1200. assert.equal(verify, result)
  1201. message = "<div>#{user.firstname} #{not.existing.test}</div>"
  1202. result = '<div>Bob -</div>'
  1203. data = {
  1204. user: {
  1205. firstname: 'Bob',
  1206. not: null,
  1207. },
  1208. }
  1209. verify = App.Utils.replaceTags(message, data)
  1210. assert.equal(verify, result)
  1211. message = "<div>#{user.firstname} #{not.existing.test}</div>"
  1212. result = '<div>Bob -</div>'
  1213. data = {
  1214. user: {
  1215. firstname: 'Bob',
  1216. not: {},
  1217. },
  1218. }
  1219. verify = App.Utils.replaceTags(message, data)
  1220. assert.equal(verify, result)
  1221. message = "<div>#{user.firstname} #{<a href=\"/test\">user.lastname</a>}</div>"
  1222. result = '<div>Bob Smith</div>'
  1223. data = {
  1224. user: {
  1225. firstname: 'Bob',
  1226. lastname: 'Smith',
  1227. },
  1228. }
  1229. verify = App.Utils.replaceTags(message, data)
  1230. assert.equal(verify, result)
  1231. user = new App.User({
  1232. firstname: 'Bob',
  1233. lastname: 'Smith Good',
  1234. created_at: '2018-10-31T10:00:00Z',
  1235. })
  1236. message = "<div>#{user.firstname} #{user.created_at}</div>"
  1237. result = '<div>Bob ' + formatTimestamp('2018-10-31T10:00:00Z') + '</div>'
  1238. data = {
  1239. user: user
  1240. }
  1241. verify = App.Utils.replaceTags(message, data)
  1242. assert.equal(verify, result)
  1243. message = "<div>#{user.firstname} #{user.created_at.date}</div>"
  1244. result = '<div>Bob -</div>'
  1245. data = {
  1246. user: user
  1247. }
  1248. verify = App.Utils.replaceTags(message, data)
  1249. assert.equal(verify, result)
  1250. message = "<div>#{user.firstname} #{user.created.date}</div>"
  1251. result = '<div>Bob -</div>'
  1252. data = {
  1253. user: user
  1254. }
  1255. verify = App.Utils.replaceTags(message, data)
  1256. assert.equal(verify, result)
  1257. message = "<a href=\"https://example.co/q=#{user.lastname}\">some text</a>"
  1258. result = '<a href=\"https://example.co/q=Smith%20Good\">some text</a>'
  1259. data = {
  1260. user: user
  1261. }
  1262. verify = App.Utils.replaceTags(message, data, true)
  1263. assert.equal(verify, result)
  1264. });
  1265. // check attibute validation
  1266. QUnit.test("check attibute validation", assert => {
  1267. var string = '123'
  1268. var result = '123'
  1269. var verify = App.Utils.htmlAttributeCleanup(string)
  1270. assert.equal(verify, result, string)
  1271. string = '123!'
  1272. result = '123'
  1273. verify = App.Utils.htmlAttributeCleanup(string)
  1274. assert.equal(verify, result, string)
  1275. string = '12 3!'
  1276. result = '123'
  1277. verify = App.Utils.htmlAttributeCleanup(string)
  1278. assert.equal(verify, result, string)
  1279. string = '12-3!'
  1280. result = '12-3'
  1281. verify = App.Utils.htmlAttributeCleanup(string)
  1282. assert.equal(verify, result, string)
  1283. string = '12_3!'
  1284. result = '12_3'
  1285. verify = App.Utils.htmlAttributeCleanup(string)
  1286. assert.equal(verify, result, string)
  1287. string = '^12_3!'
  1288. result = '12_3'
  1289. verify = App.Utils.htmlAttributeCleanup(string)
  1290. assert.equal(verify, result, string)
  1291. string = '^1\n 2_3!'
  1292. result = '12_3'
  1293. verify = App.Utils.htmlAttributeCleanup(string)
  1294. assert.equal(verify, result, string)
  1295. string = 'abc?'
  1296. result = 'abc'
  1297. verify = App.Utils.htmlAttributeCleanup(string)
  1298. assert.equal(verify, result, string)
  1299. string = 'abc."'
  1300. result = 'abc'
  1301. verify = App.Utils.htmlAttributeCleanup(string)
  1302. assert.equal(verify, result, string)
  1303. string = '#abc!^'
  1304. result = 'abc'
  1305. verify = App.Utils.htmlAttributeCleanup(string)
  1306. assert.equal(verify, result, string)
  1307. string = 'abc()=$'
  1308. result = 'abc'
  1309. verify = App.Utils.htmlAttributeCleanup(string)
  1310. assert.equal(verify, result, string)
  1311. string = "abc()=$\n123\rß"
  1312. result = 'abc123'
  1313. verify = App.Utils.htmlAttributeCleanup(string)
  1314. assert.equal(verify, result, string)
  1315. });
  1316. // check form diff
  1317. QUnit.test("check form diff", assert => {
  1318. var dataNow = {
  1319. owner_id: 1,
  1320. pending_date: '2015-01-28T09:39:00Z',
  1321. }
  1322. var dataLast = {
  1323. owner_id: '',
  1324. pending_date: '2015-01-28T09:39:00Z',
  1325. }
  1326. var diff = {}
  1327. var result = App.Utils.formDiff(dataNow, dataLast)
  1328. assert.deepEqual(result, diff, 'check form diff')
  1329. dataNow = {
  1330. owner_id: '1',
  1331. pending_date: '2015-01-28T09:39:00Z',
  1332. }
  1333. dataLast = {
  1334. owner_id: '',
  1335. pending_date: '2015-01-28T09:39:00Z',
  1336. }
  1337. diff = {}
  1338. result = App.Utils.formDiff(dataNow, dataLast)
  1339. assert.deepEqual(result, diff, 'check form diff')
  1340. dataNow = {
  1341. pending_date: '2015-01-28T09:39:00Z',
  1342. }
  1343. dataLast = {
  1344. owner_id: 1,
  1345. pending_date: '2015-01-28T09:39:00Z',
  1346. }
  1347. diff = {}
  1348. result = App.Utils.formDiff(dataNow, dataLast)
  1349. assert.deepEqual(result, diff, 'check form diff')
  1350. dataNow = {
  1351. owner_id: '',
  1352. pending_date: '2015-01-28T09:39:00Z',
  1353. }
  1354. dataLast = {
  1355. pending_date: '2015-01-28T09:39:00Z',
  1356. }
  1357. diff = {
  1358. }
  1359. result = App.Utils.formDiff(dataNow, dataLast)
  1360. assert.deepEqual(result, diff, 'check form diff')
  1361. dataNow = {
  1362. owner_id: '',
  1363. state_ids: [1,5,6,7],
  1364. }
  1365. dataLast = {}
  1366. diff = {
  1367. state_ids: ['1','5','6','7'],
  1368. }
  1369. result = App.Utils.formDiff(dataNow, dataLast)
  1370. assert.deepEqual(result, diff, 'check form diff')
  1371. dataNow = {
  1372. owner_id: 1,
  1373. state_ids: [1,5,7,6],
  1374. }
  1375. dataLast = {
  1376. owner_id: '',
  1377. state_ids: [1,5,6,7],
  1378. }
  1379. diff = {}
  1380. result = App.Utils.formDiff(dataNow, dataLast)
  1381. assert.deepEqual(result, diff, 'check form diff')
  1382. dataNow = {
  1383. owner_id: 1,
  1384. state_ids: [1,5,6,7],
  1385. }
  1386. dataLast = {
  1387. state_ids: ['1','5','7'],
  1388. }
  1389. diff = {
  1390. state_ids: ['6'],
  1391. }
  1392. result = App.Utils.formDiff(dataNow, dataLast)
  1393. assert.deepEqual(result, diff, 'check form diff')
  1394. dataNow = {
  1395. owner_id: '',
  1396. state_ids: [1,5,6,7],
  1397. }
  1398. dataLast = {
  1399. owner_id: 1,
  1400. state_ids: [1,5,6,7],
  1401. }
  1402. diff = {}
  1403. result = App.Utils.formDiff(dataNow, dataLast)
  1404. assert.deepEqual(result, diff, 'check form diff')
  1405. dataNow = {
  1406. owner_id: '',
  1407. state_ids: [1,5,6,7],
  1408. }
  1409. dataLast = {
  1410. owner_id: 5,
  1411. state_ids: [1,5,6,7],
  1412. }
  1413. diff = {
  1414. owner_id: ''
  1415. }
  1416. result = App.Utils.formDiff(dataNow, dataLast)
  1417. assert.deepEqual(result, diff, 'check form diff')
  1418. dataNow = {
  1419. state_id: 4,
  1420. pending_time: '2015-01-28T11:34:00Z'
  1421. }
  1422. dataLast = {
  1423. state_id: 5,
  1424. pending_time: undefined
  1425. }
  1426. diff = {
  1427. state_id: '4',
  1428. pending_time: '2015-01-28T11:34:00Z'
  1429. }
  1430. result = App.Utils.formDiff(dataNow, dataLast)
  1431. assert.deepEqual(result, diff, 'check form diff')
  1432. dataNow = {
  1433. pending_time: undefined
  1434. }
  1435. dataLast = {
  1436. pending_time: null
  1437. }
  1438. diff = {}
  1439. result = App.Utils.formDiff(dataNow, dataLast)
  1440. assert.deepEqual(result, diff, 'check form diff')
  1441. dataNow = {
  1442. ticket: {
  1443. pending_time: undefined,
  1444. },
  1445. }
  1446. dataLast = {
  1447. ticket: {
  1448. pending_time: null,
  1449. },
  1450. }
  1451. diff = {}
  1452. result = App.Utils.formDiff(dataNow, dataLast)
  1453. assert.deepEqual(result, diff, 'check form diff')
  1454. dataNow = {
  1455. test: '123',
  1456. ticket: {
  1457. pending_time: undefined,
  1458. },
  1459. }
  1460. dataLast = {
  1461. test: '123',
  1462. ticket: {
  1463. pending_time: null,
  1464. },
  1465. }
  1466. diff = {}
  1467. result = App.Utils.formDiff(dataNow, dataLast)
  1468. assert.deepEqual(result, diff, 'check form diff')
  1469. dataNow = {
  1470. test: '123',
  1471. }
  1472. dataLast = {}
  1473. diff = {
  1474. test: '123',
  1475. }
  1476. result = App.Utils.formDiff(dataNow, dataLast)
  1477. assert.deepEqual(result, diff, 'check form diff')
  1478. dataNow = {
  1479. test: '123',
  1480. }
  1481. dataLast = {
  1482. test: [1,2,3,4]
  1483. }
  1484. diff = {
  1485. test: '123',
  1486. }
  1487. result = App.Utils.formDiff(dataNow, dataLast)
  1488. assert.deepEqual(result, diff, 'check form diff')
  1489. dataNow = {
  1490. test: '123',
  1491. }
  1492. dataLast = {
  1493. test: {
  1494. 1: 1,
  1495. 2: 2,
  1496. }
  1497. }
  1498. diff = {
  1499. test: '123',
  1500. }
  1501. result = App.Utils.formDiff(dataNow, dataLast)
  1502. assert.deepEqual(result, diff, 'check form diff')
  1503. dataNow = {
  1504. test: [1,2,3,'4']
  1505. }
  1506. dataLast = {
  1507. test: '123',
  1508. }
  1509. diff = {
  1510. test: ['1','2','3','4']
  1511. }
  1512. result = App.Utils.formDiff(dataNow, dataLast)
  1513. assert.deepEqual(result, diff, 'check form diff')
  1514. dataNow = {
  1515. test: {
  1516. 1: 1,
  1517. 2: 2,
  1518. }
  1519. }
  1520. dataLast = {
  1521. test: '123',
  1522. }
  1523. diff = {
  1524. test: {
  1525. 1: '1',
  1526. 2: '2',
  1527. }
  1528. }
  1529. result = App.Utils.formDiff(dataNow, dataLast)
  1530. assert.deepEqual(result, diff, 'check form diff')
  1531. // regression test for issue #2042 - incorrect notification when closing a tab after setting up an object
  1532. // A newly created attribute will have the empty string as its value, this should be ignored for formDiff comparison
  1533. dataNow = {
  1534. test: '',
  1535. }
  1536. dataLast = {}
  1537. diff = {}
  1538. result = App.Utils.formDiff(dataNow, dataLast)
  1539. assert.deepEqual(result, diff, 'check form diff for a newly created attribute that is blank')
  1540. dataNow = {
  1541. test: '',
  1542. }
  1543. dataLast = {
  1544. test: '123',
  1545. }
  1546. diff = {
  1547. test: '',
  1548. }
  1549. result = App.Utils.formDiff(dataNow, dataLast)
  1550. assert.deepEqual(result, diff, 'check form diff for setting a previously valid value to blank')
  1551. dataNow = {
  1552. test: '123',
  1553. ticket: {
  1554. pending_time: undefined,
  1555. },
  1556. }
  1557. dataLast = {
  1558. ticket: {
  1559. pending_time: null,
  1560. },
  1561. }
  1562. diff = {
  1563. test: '123',
  1564. }
  1565. result = App.Utils.formDiff(dataNow, dataLast)
  1566. assert.deepEqual(result, diff, 'check form diff')
  1567. dataNow = undefined
  1568. dataLast = undefined
  1569. diff = {}
  1570. result = App.Utils.formDiff(dataNow, dataLast)
  1571. assert.deepEqual(result, diff, 'check form diff')
  1572. dataNow = {}
  1573. 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}
  1574. diff = {}
  1575. result = App.Utils.formDiff(dataNow, dataLast)
  1576. assert.deepEqual(result, diff, 'check form diff')
  1577. // do not compare content of data instances/objects
  1578. no = function test_object() {
  1579. this.a = function() { return 123; }
  1580. this.b = function() { return '1234'; }
  1581. this.c = function() { return [123]; }
  1582. this.d = [1,2,3];
  1583. this.e = 'abc';
  1584. }
  1585. no1 = new no()
  1586. no2 = new no()
  1587. no3 = new no()
  1588. dataNow = {
  1589. number:'10013',
  1590. Article: [no1],
  1591. }
  1592. dataLast = {
  1593. number: "10012",
  1594. title: "some subject 123äöü",
  1595. Article: [ no2, no3 ],
  1596. }
  1597. diff = {
  1598. number:'10013',
  1599. }
  1600. result = App.Utils.formDiff(dataNow, dataLast)
  1601. assert.deepEqual(result, diff, 'check form diff')
  1602. dataNow = {
  1603. number:'10013',
  1604. Article: [no1,2],
  1605. }
  1606. dataLast = {
  1607. number: "10012",
  1608. title: "some subject 123äöü",
  1609. Article: [ no2, no3 ],
  1610. }
  1611. diff = {
  1612. number:'10013',
  1613. Article: ['2'],
  1614. }
  1615. result = App.Utils.formDiff(dataNow, dataLast)
  1616. assert.deepEqual(result, diff, 'check form diff')
  1617. });
  1618. // check decimal format
  1619. QUnit.test("check decimal format", assert => {
  1620. var string = '123'
  1621. var result = '123.00'
  1622. var verify = App.Utils.decimal(string)
  1623. assert.equal(verify, result, string)
  1624. string = '0.6'
  1625. result = '0.60'
  1626. verify = App.Utils.decimal(string)
  1627. assert.equal(verify, result, string)
  1628. string = '6'
  1629. result = '6.00'
  1630. verify = App.Utils.decimal(string)
  1631. assert.equal(verify, result, string)
  1632. string = 6.5
  1633. result = '6.50'
  1634. verify = App.Utils.decimal(string)
  1635. assert.equal(verify, result, string)
  1636. string = '111111.6'
  1637. result = '111111.60'
  1638. verify = App.Utils.decimal(string)
  1639. assert.equal(verify, result, string)
  1640. string = '111111.622'
  1641. result = '111111.62'
  1642. verify = App.Utils.decimal(string)
  1643. assert.equal(verify, result, string)
  1644. string = 'abc.6'
  1645. result = 'abc.6'
  1646. verify = App.Utils.decimal(string)
  1647. assert.equal(verify, result, string)
  1648. string = ''
  1649. result = ''
  1650. verify = App.Utils.decimal(string)
  1651. assert.equal(verify, result, string)
  1652. string = undefined
  1653. result = ''
  1654. verify = App.Utils.decimal(string)
  1655. assert.equal(verify, result, string)
  1656. string = null
  1657. result = ''
  1658. verify = App.Utils.decimal(string)
  1659. assert.equal(verify, result, string)
  1660. });
  1661. // check formatTime format
  1662. QUnit.test("check formatTime format", assert => {
  1663. var string = '123'
  1664. var result = '123'
  1665. var verify = App.Utils.formatTime(string, 0)
  1666. assert.equal(verify, result, string)
  1667. string = '6'
  1668. result = '06'
  1669. verify = App.Utils.formatTime(string, 2)
  1670. assert.equal(verify, result, string)
  1671. string = ''
  1672. result = '00'
  1673. verify = App.Utils.formatTime(string, 2)
  1674. assert.equal(verify, result, string)
  1675. string = undefined
  1676. result = ''
  1677. verify = App.Utils.formatTime(string, 2)
  1678. assert.equal(verify, result, string)
  1679. string = null
  1680. result = ''
  1681. verify = App.Utils.formatTime(string, 2)
  1682. assert.equal(verify, result, string)
  1683. });
  1684. // check diffPosition
  1685. QUnit.test("check diffPosition format", assert => {
  1686. var a = [1,2,3,4]
  1687. var b = [1,2,3,4,5]
  1688. var result = [
  1689. {
  1690. position: 4,
  1691. id: 5,
  1692. },
  1693. ]
  1694. var verify = App.Utils.diffPositionAdd(a, b)
  1695. assert.deepEqual(verify, result)
  1696. a = [2,3,4]
  1697. b = [1,2,3,4]
  1698. result = [
  1699. {
  1700. position: 0,
  1701. id: 1,
  1702. },
  1703. ]
  1704. verify = App.Utils.diffPositionAdd(a, b)
  1705. assert.deepEqual(verify, result)
  1706. a = [2,3,4]
  1707. b = [1,2,3,4,5]
  1708. result = [
  1709. {
  1710. position: 0,
  1711. id: 1,
  1712. },
  1713. {
  1714. position: 4,
  1715. id: 5,
  1716. },
  1717. ]
  1718. verify = App.Utils.diffPositionAdd(a, b)
  1719. assert.deepEqual(verify, result)
  1720. a = [2,3,4]
  1721. b = [1,99,12,2,3,4,5]
  1722. result = [
  1723. {
  1724. position: 0,
  1725. id: 1,
  1726. },
  1727. {
  1728. position: 1,
  1729. id: 99,
  1730. },
  1731. {
  1732. position: 2,
  1733. id: 12,
  1734. },
  1735. {
  1736. position: 6,
  1737. id: 5,
  1738. },
  1739. ]
  1740. verify = App.Utils.diffPositionAdd(a, b)
  1741. assert.deepEqual(verify, result)
  1742. a = [4,3,1]
  1743. b = [1,2,3,4,5]
  1744. result = false
  1745. verify = App.Utils.diffPositionAdd(a, b)
  1746. assert.deepEqual(verify, result)
  1747. a = ['Ticket-347', 'TicketCreateScreen-2217']
  1748. b = ['Ticket-347', 'TicketCreateScreen-2217', 'TicketCreateScreen-71517']
  1749. result = [
  1750. {
  1751. position: 2,
  1752. id: 'TicketCreateScreen-71517',
  1753. },
  1754. ]
  1755. verify = App.Utils.diffPositionAdd(a, b)
  1756. assert.deepEqual(verify, result)
  1757. });
  1758. // check textLengthWithUrl format
  1759. QUnit.test("check textLengthWithUrl format", assert => {
  1760. var string = '123'
  1761. var result = 3
  1762. var verify = App.Utils.textLengthWithUrl(string)
  1763. assert.equal(verify, result)
  1764. string = '123 http is not here'
  1765. result = 20
  1766. verify = App.Utils.textLengthWithUrl(string)
  1767. assert.equal(verify, result)
  1768. string = '123 http://host is not here'
  1769. result = 39
  1770. verify = App.Utils.textLengthWithUrl(string)
  1771. assert.equal(verify, result)
  1772. string = '123 http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX is not here'
  1773. result = 39
  1774. verify = App.Utils.textLengthWithUrl(string)
  1775. assert.equal(verify, result)
  1776. string = 'http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1777. result = 23
  1778. verify = App.Utils.textLengthWithUrl(string)
  1779. assert.equal(verify, result)
  1780. string = 'http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, some other text'
  1781. result = 23 + 17
  1782. verify = App.Utils.textLengthWithUrl(string)
  1783. assert.equal(verify, result)
  1784. string = 'some other text,http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
  1785. result = 23 + 16
  1786. verify = App.Utils.textLengthWithUrl(string)
  1787. assert.equal(verify, result)
  1788. string = 'some other text, http://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX?abc=123;aaa=ab+c usw'
  1789. result = 23 + 21
  1790. verify = App.Utils.textLengthWithUrl(string)
  1791. assert.equal(verify, result)
  1792. });
  1793. // check getRecipientArticle format
  1794. QUnit.test('check getRecipientArticle format', assert => {
  1795. var customer = {
  1796. login: 'login',
  1797. firstname: 'firstname',
  1798. lastname: 'lastname',
  1799. email: 'customer@example.com',
  1800. }
  1801. var ticket = {
  1802. customer: customer,
  1803. }
  1804. var article = {
  1805. type: {
  1806. name: 'phone',
  1807. },
  1808. sender: {
  1809. name: 'Customer',
  1810. },
  1811. from: customer.email,
  1812. to: 'some group',
  1813. message_id: 'message_id1',
  1814. created_by: {
  1815. login: 'login',
  1816. firstname: 'firstname',
  1817. lastname: 'lastname',
  1818. email: 'article_created_by@example.com',
  1819. },
  1820. }
  1821. var result = {
  1822. to: 'customer@example.com',
  1823. cc: '',
  1824. body: '',
  1825. in_reply_to: 'message_id1',
  1826. }
  1827. var verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  1828. assert.deepEqual(verify, result)
  1829. customer = {
  1830. login: 'login',
  1831. firstname: 'firstname',
  1832. lastname: 'lastname',
  1833. email: 'customer@example.com',
  1834. }
  1835. ticket = {
  1836. customer: customer,
  1837. }
  1838. article = {
  1839. type: {
  1840. name: 'phone',
  1841. },
  1842. sender: {
  1843. name: 'Customer',
  1844. },
  1845. from: customer.email,
  1846. message_id: 'message_id2',
  1847. created_by: {
  1848. login: 'login',
  1849. firstname: 'firstname',
  1850. lastname: 'lastname',
  1851. email: 'article_created_by@example.com',
  1852. },
  1853. }
  1854. result = {
  1855. to: customer.email,
  1856. cc: '',
  1857. body: '',
  1858. in_reply_to: 'message_id2',
  1859. }
  1860. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  1861. assert.deepEqual(verify, result)
  1862. customer = {
  1863. login: 'login',
  1864. firstname: 'firstname',
  1865. lastname: 'lastname',
  1866. email: 'customer@example.com',
  1867. }
  1868. ticket = {
  1869. customer: customer,
  1870. }
  1871. article = {
  1872. message_id: 'message_id3',
  1873. type: {
  1874. name: 'phone',
  1875. },
  1876. sender: {
  1877. name: 'Agent',
  1878. },
  1879. from: 'article_created_by@example.com',
  1880. created_by: {
  1881. login: 'login',
  1882. firstname: 'firstname',
  1883. lastname: 'lastname',
  1884. email: 'article_created_by@example.com',
  1885. },
  1886. }
  1887. result = {
  1888. to: 'customer@example.com',
  1889. cc: '',
  1890. body: '',
  1891. in_reply_to: 'message_id3',
  1892. }
  1893. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  1894. assert.deepEqual(verify, result)
  1895. customer = {
  1896. login: 'login',
  1897. firstname: 'firstname',
  1898. lastname: 'lastname',
  1899. email: 'customer@example.com',
  1900. }
  1901. ticket = {
  1902. customer: customer,
  1903. }
  1904. article = {
  1905. message_id: 'message_id4',
  1906. created_by: customer,
  1907. type: {
  1908. name: 'web',
  1909. },
  1910. sender: {
  1911. name: 'Customer',
  1912. },
  1913. from: customer.email,
  1914. to: 'some group',
  1915. created_by: {
  1916. login: 'login',
  1917. firstname: 'firstname',
  1918. lastname: 'lastname',
  1919. email: 'article_created_by@example.com',
  1920. },
  1921. }
  1922. result = {
  1923. to: 'customer@example.com',
  1924. cc: '',
  1925. body: '',
  1926. in_reply_to: 'message_id4',
  1927. }
  1928. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  1929. assert.deepEqual(verify, result)
  1930. customer = {
  1931. login: 'login',
  1932. firstname: 'firstname',
  1933. lastname: 'lastname',
  1934. email: 'customer@example.com',
  1935. }
  1936. ticket = {
  1937. customer: customer,
  1938. }
  1939. article = {
  1940. message_id: 'message_id5',
  1941. type: {
  1942. name: 'web',
  1943. },
  1944. sender: {
  1945. name: 'Customer',
  1946. },
  1947. from: customer.email,
  1948. created_by: {
  1949. login: 'login',
  1950. firstname: 'firstname',
  1951. lastname: 'lastname',
  1952. email: 'article_created_by@example.com',
  1953. }
  1954. }
  1955. result = {
  1956. to: 'customer@example.com',
  1957. cc: '',
  1958. body: '',
  1959. in_reply_to: 'message_id5',
  1960. }
  1961. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  1962. assert.deepEqual(verify, result)
  1963. customer = {
  1964. login: 'login',
  1965. firstname: 'firstname',
  1966. lastname: 'lastname',
  1967. email: 'customer@example.com',
  1968. }
  1969. ticket = {
  1970. customer: customer,
  1971. }
  1972. article = {
  1973. message_id: 'message_id6',
  1974. type: {
  1975. name: 'email',
  1976. },
  1977. sender: {
  1978. name: 'Customer',
  1979. },
  1980. from: customer.email,
  1981. to: 'some group',
  1982. created_by: {
  1983. login: 'login',
  1984. firstname: 'firstname',
  1985. lastname: 'lastname',
  1986. email: 'article_created_by@example.com',
  1987. }
  1988. }
  1989. result = {
  1990. to: 'customer@example.com',
  1991. cc: '',
  1992. body: '',
  1993. in_reply_to: 'message_id6',
  1994. }
  1995. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  1996. assert.deepEqual(verify, result)
  1997. customer = {
  1998. login: 'login',
  1999. firstname: 'firstname',
  2000. lastname: 'lastname',
  2001. email: 'customer@example.com',
  2002. }
  2003. ticket = {
  2004. customer: customer,
  2005. }
  2006. article = {
  2007. message_id: 'message_id7',
  2008. type: {
  2009. name: 'email',
  2010. },
  2011. sender: {
  2012. name: 'Customer',
  2013. },
  2014. from: 'some other invalid part, ' + customer.email,
  2015. to: 'some group',
  2016. created_by: {
  2017. login: 'login',
  2018. firstname: 'firstname',
  2019. lastname: 'lastname',
  2020. email: 'article_created_by@example.com',
  2021. }
  2022. }
  2023. result = {
  2024. to: 'customer@example.com',
  2025. cc: '',
  2026. body: '',
  2027. in_reply_to: 'message_id7',
  2028. }
  2029. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2030. console.log(verify)
  2031. assert.deepEqual(verify, result)
  2032. customer = {
  2033. login: 'login',
  2034. firstname: 'firstname',
  2035. lastname: 'lastname',
  2036. email: 'customer@example.com',
  2037. }
  2038. ticket = {
  2039. customer: customer,
  2040. }
  2041. article = {
  2042. message_id: 'message_id7.1',
  2043. type: {
  2044. name: 'email',
  2045. },
  2046. sender: {
  2047. name: 'Customer',
  2048. },
  2049. from: 'some other invalid part, Some Realname ' + customer.email,
  2050. to: 'some group',
  2051. created_by: {
  2052. login: 'login',
  2053. firstname: 'firstname',
  2054. lastname: 'lastname',
  2055. email: 'article_created_by@example.com',
  2056. }
  2057. }
  2058. result = {
  2059. to: 'customer@example.com',
  2060. cc: '',
  2061. body: '',
  2062. in_reply_to: 'message_id7.1',
  2063. }
  2064. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2065. console.log(verify)
  2066. assert.deepEqual(verify, result)
  2067. customer = {
  2068. login: 'login',
  2069. firstname: 'firstname',
  2070. lastname: 'lastname',
  2071. email: 'customer@example.com',
  2072. }
  2073. ticket = {
  2074. customer: customer,
  2075. }
  2076. article = {
  2077. message_id: 'message_id7.2',
  2078. type: {
  2079. name: 'email',
  2080. },
  2081. sender: {
  2082. name: 'Customer',
  2083. },
  2084. from: 'some other invalid part, Some Realname ' + customer.email + ' , abc',
  2085. to: 'some group',
  2086. created_by: {
  2087. login: 'login',
  2088. firstname: 'firstname',
  2089. lastname: 'lastname',
  2090. email: 'article_created_by@example.com',
  2091. }
  2092. }
  2093. result = {
  2094. to: 'customer@example.com',
  2095. cc: '',
  2096. body: '',
  2097. in_reply_to: 'message_id7.2',
  2098. }
  2099. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2100. console.log(verify)
  2101. assert.deepEqual(verify, result)
  2102. customer = {
  2103. login: 'login',
  2104. firstname: 'firstname',
  2105. lastname: 'lastname',
  2106. email: 'customer@example.com',
  2107. }
  2108. agent = {
  2109. login: 'login',
  2110. firstname: 'firstname',
  2111. lastname: 'lastname',
  2112. email: 'agent@example.com',
  2113. }
  2114. ticket = {
  2115. customer: customer,
  2116. }
  2117. article = {
  2118. message_id: 'message_id8',
  2119. created_by: agent,
  2120. type: {
  2121. name: 'email',
  2122. },
  2123. sender: {
  2124. name: 'Agent',
  2125. },
  2126. from: 'customer2@example.com',
  2127. to: 'customer@example.com',
  2128. }
  2129. result = {
  2130. to: 'customer2@example.com',
  2131. cc: '',
  2132. body: '',
  2133. in_reply_to: 'message_id8',
  2134. }
  2135. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2136. assert.deepEqual(verify, result)
  2137. customer = {
  2138. login: 'login',
  2139. firstname: 'firstname',
  2140. lastname: 'lastname',
  2141. email: 'customer@example.com',
  2142. }
  2143. agent = {
  2144. login: 'login',
  2145. firstname: 'firstname',
  2146. lastname: 'lastname',
  2147. email: 'agent@example.com',
  2148. }
  2149. ticket = {
  2150. customer: customer,
  2151. }
  2152. article = {
  2153. message_id: 'message_id9',
  2154. created_by: agent,
  2155. type: {
  2156. name: 'email',
  2157. },
  2158. sender: {
  2159. name: 'Agent',
  2160. },
  2161. from: 'agent@example.com',
  2162. to: 'customer@example.com',
  2163. }
  2164. result = {
  2165. to: 'customer@example.com',
  2166. cc: '',
  2167. body: '',
  2168. in_reply_to: 'message_id9',
  2169. }
  2170. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2171. assert.deepEqual(verify, result)
  2172. customer = {
  2173. login: 'login',
  2174. firstname: 'firstname',
  2175. lastname: 'lastname',
  2176. email: 'customer@example.com',
  2177. }
  2178. agent = {
  2179. login: 'login',
  2180. firstname: 'firstname',
  2181. lastname: 'lastname',
  2182. email: 'agent@example.com',
  2183. }
  2184. ticket = {
  2185. customer: customer,
  2186. }
  2187. article = {
  2188. message_id: 'message_id10',
  2189. created_by: agent,
  2190. type: {
  2191. name: 'email',
  2192. },
  2193. sender: {
  2194. name: 'Agent',
  2195. },
  2196. from: 'Agent@Example.com',
  2197. to: 'customer@example.com',
  2198. cc: 'zammad@example.com',
  2199. }
  2200. result = {
  2201. to: 'customer@example.com',
  2202. cc: '',
  2203. body: '',
  2204. in_reply_to: 'message_id10',
  2205. }
  2206. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2207. assert.deepEqual(verify, result)
  2208. customer = {
  2209. login: 'login',
  2210. firstname: 'firstname',
  2211. lastname: 'lastname',
  2212. email: 'customer@example.com',
  2213. }
  2214. agent = {
  2215. login: 'login',
  2216. firstname: 'firstname',
  2217. lastname: 'lastname',
  2218. email: 'agent@example.com',
  2219. }
  2220. ticket = {
  2221. customer: customer,
  2222. }
  2223. article = {
  2224. message_id: 'message_id11',
  2225. created_by: agent,
  2226. type: {
  2227. name: 'email',
  2228. },
  2229. sender: {
  2230. name: 'Agent',
  2231. },
  2232. from: 'Agent@Example.com',
  2233. to: 'customer@example.com, agent@example.com',
  2234. cc: 'zammad@example.com',
  2235. }
  2236. result = {
  2237. to: 'customer@example.com, agent@example.com',
  2238. cc: 'zammad@example.com',
  2239. body: '',
  2240. in_reply_to: 'message_id11',
  2241. }
  2242. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type, [], true)
  2243. assert.deepEqual(verify, result)
  2244. customer = {
  2245. login: 'login',
  2246. firstname: 'firstname',
  2247. lastname: 'lastname',
  2248. email: 'customer@example.com',
  2249. }
  2250. agent = {
  2251. login: 'login',
  2252. firstname: 'firstname',
  2253. lastname: 'lastname',
  2254. email: 'agent@example.com',
  2255. }
  2256. ticket = {
  2257. customer: customer,
  2258. }
  2259. article = {
  2260. message_id: 'message_id12',
  2261. created_by: agent,
  2262. type: {
  2263. name: 'email',
  2264. },
  2265. sender: {
  2266. name: 'Agent',
  2267. },
  2268. from: 'Agent@Example.com',
  2269. to: 'customeR@EXAMPLE.com, agent@example.com',
  2270. cc: 'zammad@example.com, customer@example.com',
  2271. }
  2272. result = {
  2273. to: 'customer@example.com, agent@example.com',
  2274. cc: 'zammad@example.com',
  2275. body: '',
  2276. in_reply_to: 'message_id12',
  2277. }
  2278. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, [], true)
  2279. assert.deepEqual(verify, result)
  2280. customer = {
  2281. login: 'login',
  2282. firstname: 'firstname',
  2283. lastname: 'lastname',
  2284. email: 'customer@example.com',
  2285. }
  2286. agent = {
  2287. login: 'login',
  2288. firstname: 'firstname',
  2289. lastname: 'lastname',
  2290. email: 'agent@example.com',
  2291. }
  2292. ticket = {
  2293. customer: customer,
  2294. }
  2295. article = {
  2296. message_id: 'message_id13',
  2297. created_by: agent,
  2298. type: {
  2299. name: 'email',
  2300. },
  2301. sender: {
  2302. name: 'Agent',
  2303. },
  2304. from: 'Agent@Example.com',
  2305. to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
  2306. cc: 'zammad@example.com, customer2@example.com',
  2307. }
  2308. result = {
  2309. to: 'customer@example.com, agent@example.com',
  2310. cc: 'customer2@example.com',
  2311. body: '',
  2312. in_reply_to: 'message_id13',
  2313. }
  2314. email_addresses = [
  2315. {
  2316. email: 'zammad@example.com',
  2317. },
  2318. {
  2319. email: 'zammad2@example.com',
  2320. }
  2321. ]
  2322. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2323. assert.deepEqual(verify, result)
  2324. customer = {
  2325. login: 'login',
  2326. firstname: 'firstname',
  2327. lastname: 'lastname',
  2328. email: 'customer@example.com',
  2329. }
  2330. agent = {
  2331. login: 'login',
  2332. firstname: 'firstname',
  2333. lastname: 'lastname',
  2334. email: 'AGENT@example.com',
  2335. }
  2336. ticket = {
  2337. customer: customer,
  2338. }
  2339. article = {
  2340. message_id: 'message_id14',
  2341. created_by: agent,
  2342. type: {
  2343. name: 'email',
  2344. },
  2345. sender: {
  2346. name: 'Agent',
  2347. },
  2348. from: 'Agent@Example.com',
  2349. to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
  2350. cc: 'zammad@example.com, customer2@example.com',
  2351. }
  2352. result = {
  2353. to: 'customer@example.com, agent@example.com',
  2354. cc: 'customer2@example.com',
  2355. body: '',
  2356. in_reply_to: 'message_id14',
  2357. }
  2358. email_addresses = [
  2359. {
  2360. email: 'zammad@example.com',
  2361. },
  2362. {
  2363. email: 'zammad2@example.com',
  2364. }
  2365. ]
  2366. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2367. assert.deepEqual(verify, result)
  2368. customer = {
  2369. login: 'login',
  2370. firstname: 'firstname',
  2371. lastname: 'lastname',
  2372. email: 'zammad@example.com',
  2373. }
  2374. ticket = {
  2375. customer: customer,
  2376. }
  2377. article = {
  2378. message_id: 'message_id15',
  2379. created_by: customer,
  2380. type: {
  2381. name: 'email',
  2382. },
  2383. sender: {
  2384. name: 'Agent',
  2385. },
  2386. from: 'zammad@EXAMPLE.com',
  2387. to: 'customeR@EXAMPLE.com, agent@example.com, zammad2@EXAMPLE.com',
  2388. cc: 'zammad@example.com, customer2@example.com',
  2389. }
  2390. result = {
  2391. to: 'customer@example.com, agent@example.com',
  2392. cc: 'customer2@example.com',
  2393. body: '',
  2394. in_reply_to: 'message_id15',
  2395. }
  2396. email_addresses = [
  2397. {
  2398. email: 'zammad@example.com',
  2399. },
  2400. {
  2401. email: 'zammad2@example.com',
  2402. }
  2403. ]
  2404. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2405. assert.deepEqual(verify, result)
  2406. customer = {
  2407. login: 'login',
  2408. firstname: 'firstname',
  2409. lastname: 'lastname',
  2410. email: 'customer@example.com',
  2411. }
  2412. ticket = {
  2413. customer: customer,
  2414. }
  2415. article = {
  2416. message_id: 'message_id16',
  2417. created_by: customer,
  2418. type: {
  2419. name: 'email',
  2420. },
  2421. sender: {
  2422. name: 'Agent',
  2423. },
  2424. from: 'customer@example.com',
  2425. to: 'customer1@example.com, customer2@example.com, zammad@example.com',
  2426. cc: '',
  2427. }
  2428. result = {
  2429. to: 'customer1@example.com, customer2@example.com, customer@example.com',
  2430. cc: '',
  2431. body: '',
  2432. in_reply_to: 'message_id16',
  2433. }
  2434. email_addresses = [
  2435. {
  2436. email: 'zammad@example.com',
  2437. },
  2438. {
  2439. email: 'zammad2@example.com',
  2440. }
  2441. ]
  2442. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2443. assert.deepEqual(verify, result)
  2444. customer = {
  2445. login: 'login',
  2446. firstname: 'firstname',
  2447. lastname: 'lastname',
  2448. email: 'customer@example.com',
  2449. }
  2450. ticket = {
  2451. customer: customer,
  2452. }
  2453. article = {
  2454. message_id: 'message_id17',
  2455. created_by: customer,
  2456. type: {
  2457. name: 'email',
  2458. },
  2459. sender: {
  2460. name: 'Agent',
  2461. },
  2462. from: 'customer@example.com',
  2463. to: 'customer1@example.com, customer2@example.com, zammad@example.com, customer2+2@example.com',
  2464. cc: '',
  2465. }
  2466. result = {
  2467. to: 'customer1@example.com, customer2@example.com, customer2+2@example.com, customer@example.com',
  2468. cc: '',
  2469. body: '',
  2470. in_reply_to: 'message_id17',
  2471. }
  2472. email_addresses = [
  2473. {
  2474. email: 'zammad@example.com',
  2475. },
  2476. {
  2477. email: 'zammad2@example.com',
  2478. }
  2479. ]
  2480. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2481. assert.deepEqual(verify, result)
  2482. customer = {
  2483. login: 'login',
  2484. firstname: 'firstname',
  2485. lastname: 'lastname',
  2486. email: 'customer@example.com',
  2487. }
  2488. agent = {
  2489. login: 'login',
  2490. firstname: 'firstname',
  2491. lastname: 'lastname',
  2492. email: 'zammad@example.com',
  2493. }
  2494. ticket = {
  2495. customer: customer,
  2496. }
  2497. article = {
  2498. message_id: 'message_id18',
  2499. created_by: agent,
  2500. type: {
  2501. name: 'email',
  2502. },
  2503. sender: {
  2504. name: 'Agent',
  2505. },
  2506. from: 'zammad@example.com',
  2507. to: 'customer@example.com',
  2508. cc: '',
  2509. }
  2510. result = {
  2511. to: 'customer@example.com',
  2512. cc: '',
  2513. body: '',
  2514. in_reply_to: 'message_id18',
  2515. }
  2516. email_addresses = [
  2517. {
  2518. email: 'zammad@example.com',
  2519. },
  2520. {
  2521. email: 'zammad2@example.com',
  2522. }
  2523. ]
  2524. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, true)
  2525. assert.deepEqual(verify, result)
  2526. customer = {
  2527. login: 'login',
  2528. firstname: 'firstname',
  2529. lastname: 'lastname',
  2530. email: 'customer@example.com',
  2531. }
  2532. agent = {
  2533. login: 'login',
  2534. firstname: 'firstname',
  2535. lastname: 'lastname',
  2536. email: 'zammad@example.com',
  2537. }
  2538. ticket = {
  2539. customer: customer,
  2540. }
  2541. article = {
  2542. message_id: 'message_id19',
  2543. created_by: agent,
  2544. type: {
  2545. name: 'email',
  2546. },
  2547. sender: {
  2548. name: 'Agent',
  2549. },
  2550. from: 'Sender <zammad@example.com>',
  2551. to: 'Customer <customer@example.com>',
  2552. cc: '',
  2553. }
  2554. result = {
  2555. to: 'customer@example.com',
  2556. cc: '',
  2557. body: '',
  2558. in_reply_to: 'message_id19',
  2559. }
  2560. email_addresses = [
  2561. {
  2562. email: 'zammad@example.com',
  2563. },
  2564. {
  2565. email: 'zammad2@example.com',
  2566. }
  2567. ]
  2568. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, false)
  2569. assert.deepEqual(verify, result)
  2570. agent = {
  2571. login: 'login',
  2572. firstname: 'firstname',
  2573. lastname: 'lastname',
  2574. email: 'agent@example.com',
  2575. }
  2576. ticket = {
  2577. customer: agent,
  2578. }
  2579. article = {
  2580. message_id: 'message_id20',
  2581. created_by: agent,
  2582. type: {
  2583. name: 'email',
  2584. },
  2585. sender: {
  2586. name: 'Agent',
  2587. },
  2588. from: 'Agent <Agent@Example.com>',
  2589. to: 'Sender <zammad@example.com>',
  2590. cc: '',
  2591. }
  2592. result = {
  2593. to: 'agent@example.com',
  2594. cc: '',
  2595. body: '',
  2596. in_reply_to: 'message_id20',
  2597. }
  2598. email_addresses = [
  2599. {
  2600. email: 'zammad@example.com',
  2601. },
  2602. {
  2603. email: 'zammad2@example.com',
  2604. }
  2605. ]
  2606. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, false)
  2607. assert.deepEqual(verify, result)
  2608. agent = {
  2609. login: 'login',
  2610. firstname: 'firstname',
  2611. lastname: 'lastname',
  2612. email: 'agent@example.com',
  2613. }
  2614. ticket = {
  2615. customer: agent,
  2616. }
  2617. article = {
  2618. message_id: 'message_id20',
  2619. created_by: agent,
  2620. type: {
  2621. name: 'email',
  2622. },
  2623. sender: {
  2624. name: 'Agent',
  2625. },
  2626. from: 'Agent <Agent@Example.com>',
  2627. to: 'somebodyelse@example.com, Zammad <zammad@example.com>',
  2628. cc: '',
  2629. }
  2630. result = {
  2631. to: 'agent@example.com',
  2632. cc: '',
  2633. body: '',
  2634. in_reply_to: 'message_id20',
  2635. }
  2636. email_addresses = [
  2637. {
  2638. email: 'zammad@example.com',
  2639. },
  2640. {
  2641. email: 'zammad2@example.com',
  2642. }
  2643. ]
  2644. verify = App.Utils.getRecipientArticle(ticket, article, agent, article.type, email_addresses, false)
  2645. assert.deepEqual(verify, result)
  2646. customer = {
  2647. login: 'login',
  2648. firstname: 'firstname',
  2649. lastname: 'lastname',
  2650. email: "'customer@example.com'",
  2651. }
  2652. agent = {
  2653. login: 'login',
  2654. firstname: 'firstname',
  2655. lastname: 'lastname',
  2656. email: 'agent@example.com',
  2657. }
  2658. ticket = {
  2659. customer: customer,
  2660. }
  2661. article = {
  2662. message_id: 'message_id21',
  2663. created_by: agent,
  2664. type: {
  2665. name: 'email',
  2666. },
  2667. sender: {
  2668. name: 'Agent',
  2669. },
  2670. from: customer.email,
  2671. to: 'agent@example.com',
  2672. }
  2673. result = {
  2674. to: 'customer@example.com',
  2675. cc: '',
  2676. body: '',
  2677. in_reply_to: 'message_id21',
  2678. }
  2679. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2680. assert.deepEqual(verify, result)
  2681. // Regression test for issue #2184
  2682. // Case 1
  2683. // 1. Create a "Received Call" Ticket for article_customer
  2684. // 2. Change the Customer of the ticket to ticket_customer (but article.from still points to article_customer)
  2685. // 3. Reply to the first Article
  2686. // Recipient SHOULD BE Article.from
  2687. var article_customer = {
  2688. login: 'login',
  2689. firstname: 'article',
  2690. lastname: 'lastname',
  2691. email: 'article_customer@example.com',
  2692. }
  2693. var ticket_customer = {
  2694. login: 'login2',
  2695. firstname: 'ticket',
  2696. lastname: 'lastname',
  2697. email: 'ticket_customer@example.com',
  2698. }
  2699. ticket = {
  2700. customer: ticket_customer,
  2701. }
  2702. article = {
  2703. type: {
  2704. name: 'phone',
  2705. },
  2706. sender: {
  2707. name: 'Customer',
  2708. },
  2709. from: 'article lastname <article_customer@example.com>',
  2710. to: 'some group',
  2711. message_id: 'message_id22',
  2712. created_by: {
  2713. login: 'login',
  2714. firstname: 'firstname',
  2715. lastname: 'lastname',
  2716. email: 'article_created_by@example.com',
  2717. },
  2718. }
  2719. result = {
  2720. to: 'article_customer@example.com',
  2721. cc: '',
  2722. body: '',
  2723. in_reply_to: 'message_id22',
  2724. }
  2725. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2726. assert.deepEqual(verify, result)
  2727. // Regression test for issue #2184
  2728. // Case 2
  2729. // 1. Create a "Outbound Call" Ticket for article_customer
  2730. // 2. Change the Customer of the Ticket to ticket_customer (but article.to still points to article_customer)
  2731. // 3. Reply to the first Article
  2732. // Recipient SHOULD BE Article.to
  2733. article_customer = {
  2734. login: 'login',
  2735. firstname: 'article',
  2736. lastname: 'lastname',
  2737. email: 'article_customer@example.com',
  2738. }
  2739. ticket_customer = {
  2740. login: 'login2',
  2741. firstname: 'ticket',
  2742. lastname: 'lastname',
  2743. email: 'ticket_customer@example.com',
  2744. }
  2745. ticket = {
  2746. customer: ticket_customer,
  2747. }
  2748. article = {
  2749. type: {
  2750. name: 'phone',
  2751. },
  2752. sender: {
  2753. name: 'Agent',
  2754. },
  2755. from: 'agent1@example.com',
  2756. to: article_customer.email,
  2757. message_id: 'message_id23',
  2758. created_by: {
  2759. login: 'login',
  2760. firstname: 'firstname',
  2761. lastname: 'lastname',
  2762. email: 'article_created_by@example.com',
  2763. },
  2764. }
  2765. result = {
  2766. to: 'article_customer@example.com',
  2767. cc: '',
  2768. body: '',
  2769. in_reply_to: 'message_id23',
  2770. }
  2771. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type)
  2772. assert.deepEqual(verify, result)
  2773. // https://github.com/zammad/zammad/issues/2551
  2774. // If "From:" is local address and "Reply-To:" is available, use it
  2775. var article_customer = {
  2776. login: 'login',
  2777. firstname: 'article',
  2778. lastname: 'lastname',
  2779. email: 'article_customer@example.com',
  2780. }
  2781. var ticket_customer = {
  2782. login: 'login2',
  2783. firstname: 'ticket',
  2784. lastname: 'lastname',
  2785. email: 'ticket_customer@example.com',
  2786. }
  2787. ticket = {
  2788. customer: ticket_customer,
  2789. }
  2790. article = {
  2791. type: {
  2792. name: 'email',
  2793. },
  2794. sender: {
  2795. name: 'Customer',
  2796. },
  2797. from: 'article lastname <article_customer@example.com>',
  2798. to: 'some group',
  2799. reply_to: 'asd@example.com',
  2800. message_id: 'message_id22',
  2801. created_by: {
  2802. login: 'login',
  2803. firstname: 'firstname',
  2804. lastname: 'lastname',
  2805. email: 'article_created_by@example.com',
  2806. },
  2807. }
  2808. email_addresses = [{ email: 'article_customer@example.com'}]
  2809. result = {
  2810. to: 'asd@example.com',
  2811. cc: '',
  2812. body: '',
  2813. in_reply_to: 'message_id22',
  2814. }
  2815. verify = App.Utils.getRecipientArticle(ticket, article, article.created_by, article.type, email_addresses)
  2816. assert.deepEqual(verify, result)
  2817. });
  2818. QUnit.test("contentTypeCleanup", assert => {
  2819. var source = "image/png"
  2820. var should = "image/png"
  2821. var result = App.Utils.contentTypeCleanup(source)
  2822. assert.equal(result, should, source)
  2823. source = "image/png; some.file"
  2824. should = "image/png"
  2825. result = App.Utils.contentTypeCleanup(source)
  2826. assert.equal(result, should, source)
  2827. source = "image/png;some.file"
  2828. should = "image/png"
  2829. result = App.Utils.contentTypeCleanup(source)
  2830. assert.equal(result, should, source)
  2831. source = "image/jpeg;some.file"
  2832. should = "image/jpeg"
  2833. result = App.Utils.contentTypeCleanup(source)
  2834. assert.equal(result, should, source)
  2835. source = "image/jpg;some.file"
  2836. should = "image/jpg"
  2837. result = App.Utils.contentTypeCleanup(source)
  2838. assert.equal(result, should, source)
  2839. source = "image/gif;some.file"
  2840. should = "image/gif"
  2841. result = App.Utils.contentTypeCleanup(source)
  2842. assert.equal(result, should, source)
  2843. source = "image/gif\n;some.file"
  2844. should = "image/gif"
  2845. result = App.Utils.contentTypeCleanup(source)
  2846. assert.equal(result, should, source)
  2847. });
  2848. // htmlImage2DataUrl
  2849. QUnit.test("htmlImage2DataUrl", assert => {
  2850. var source = '<div>test 13</div>'
  2851. var should = '<div>test 13</div>'
  2852. var result = App.Utils.htmlImage2DataUrl(source)
  2853. assert.equal(result, should, source)
  2854. source = 'some test'
  2855. should = 'some test'
  2856. result = App.Utils.htmlImage2DataUrl(source)
  2857. assert.equal(result, should, source)
  2858. source = '<img src="some url">some test'
  2859. should = '<img src="data:,">some test'
  2860. result = App.Utils.htmlImage2DataUrl(source)
  2861. assert.equal(result, should, source)
  2862. source = '<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAADAAEDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACv/EABQQAQAAAAAAAAAAAAAAAAAAAAD/xAAUAQEAAAAAAAAAAAAAAAAAAAAF/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AbgQDv//Z">some test'
  2863. should = '<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAADAAEDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACv/EABQQAQAAAAAAAAAAAAAAAAAAAAD/xAAUAQEAAAAAAAAAAAAAAAAAAAAF/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AbgQDv//Z">some test'
  2864. result = App.Utils.htmlImage2DataUrl(source)
  2865. assert.equal(result, should, source)
  2866. source = '<img src="data:image/jpeg;base64,some_data_123">some <img src="some url">test'
  2867. should = '<img src="data:image/jpeg;base64,some_data_123">some <img src="data:,">test'
  2868. result = App.Utils.htmlImage2DataUrl(source)
  2869. assert.equal(result, should, source)
  2870. // GitHub issue #2305
  2871. source = '<img src="cid:1234">some test'
  2872. should = '<img src="cid:1234">some test'
  2873. result = App.Utils.htmlImage2DataUrl(source)
  2874. assert.equal(result, should, source)
  2875. // GitHub issue #2701
  2876. source = '<img alt="foo">some test'
  2877. should = '<img alt="foo">some test'
  2878. result = App.Utils.htmlImage2DataUrl(source)
  2879. assert.equal(result, should, source)
  2880. });
  2881. QUnit.test('App.Utils.icon()', assert => {
  2882. // When given no arguments,
  2883. // expect @icon() to return null
  2884. assert.equal(App.Utils.icon(), null, 'with no arguments')
  2885. // On a modern browser and when given a single argument,
  2886. // expect @icon(name) to return an <svg> tag
  2887. window.svgPolyfill = false
  2888. svgTag = '<svg class="icon icon-foo "><use xlink:href="assets/images/icons.svg#icon-foo" /></svg>'
  2889. assert.equal(App.Utils.icon('foo'), svgTag, 'with one arg / no SVG polyfill')
  2890. // On a modern browser and when given two arguments,
  2891. // expect @icon(name) to return an <svg> tag
  2892. // with second arg as add'l class name
  2893. window.svgPolyfill = false
  2894. svgTag = '<svg class="icon icon-foo bar"><use xlink:href="assets/images/icons.svg#icon-foo" /></svg>'
  2895. assert.equal(App.Utils.icon('foo', 'bar'), svgTag, 'with two args / no SVG polyfill')
  2896. // On a browser requiring SVG polyfill and when given a single argument,
  2897. // expect @icon(name, class) to return an <svg> tag
  2898. // with pathless xlink:href attr
  2899. window.svgPolyfill = true
  2900. svgTag = '<svg class="icon icon-foo "><use xlink:href="#icon-foo" /></svg>'
  2901. assert.equal(App.Utils.icon('foo'), svgTag, 'with one arg / SVG polyfill')
  2902. // On a browser requiring SVG polyfill and when given two arguments,
  2903. // expect @icon(name, class) to return an <svg> tag
  2904. // with pathless xlink:href attr and second arg as add'l class name
  2905. window.svgPolyfill = true
  2906. svgTag = '<svg class="icon icon-foo bar"><use xlink:href="#icon-foo" /></svg>'
  2907. assert.equal(App.Utils.icon('foo', 'bar'), svgTag, 'with two args / SVG polyfill')
  2908. // For a left-to-right browser language and when given an argument containing '{start}' or '{end}',
  2909. // expect @icon(name) to return an <svg> tag
  2910. // replacing '{start}' with 'left' and '{end}' with 'right'
  2911. window.svgPolyfill = false
  2912. App.i18n.dir = function() { return 'ltr' }
  2913. svgTag = '<svg class="icon icon-arrow-left "><use xlink:href="assets/images/icons.svg#icon-arrow-left" /></svg>'
  2914. assert.equal(App.Utils.icon('arrow-{start}'), svgTag, 'for ltr locale / name includes "{start}"')
  2915. svgTag = '<svg class="icon icon-arrow-right "><use xlink:href="assets/images/icons.svg#icon-arrow-right" /></svg>'
  2916. assert.equal(App.Utils.icon('arrow-{end}'), svgTag, 'for ltr locale / name includes "{end}"')
  2917. // For a right-to-left browser language and when given an argument containing '{start}' or '{end}',
  2918. // expect @icon(name) to return an <svg> tag
  2919. // replacing '{start}' with 'left' and '{end}' with 'right'
  2920. window.svgPolyFill = false
  2921. App.i18n.dir = function() { return 'rtl' }
  2922. svgTag = '<svg class="icon icon-arrow-right "><use xlink:href="assets/images/icons.svg#icon-arrow-right" /></svg>'
  2923. assert.equal(App.Utils.icon('arrow-{start}'), svgTag, 'for rtl locale / name includes "{start}"')
  2924. svgTag = '<svg class="icon icon-arrow-left "><use xlink:href="assets/images/icons.svg#icon-arrow-left" /></svg>'
  2925. assert.equal(App.Utils.icon('arrow-{end}'), svgTag, 'for rtl locale / name includes "{end}"')
  2926. });
  2927. var source1 = '<img src="/assets/images/avatar-bg.png">some test'
  2928. $('#image2data1').html(source1)
  2929. var htmlImage2DataUrlTest1 = function() {
  2930. QUnit.test("htmlImage2DataUrl1 async", assert => {
  2931. var result1 = App.Utils.htmlImage2DataUrl(source1)
  2932. assert.ok(result1.match(/some test/), source1)
  2933. assert.ok(!result1.match(/avatar-bg.png/), source1)
  2934. assert.ok(result1.match(/^\<img src=\"data:image\/png;base64,/), source1)
  2935. });
  2936. }
  2937. $('#image2data1 img').one('load', htmlImage2DataUrlTest1)
  2938. var source2 = '<img src="/assets/images/chat-demo-avatar.png">some test'
  2939. $('#image2data2').html(source2)
  2940. var htmlImage2DataUrlTest2Success = function(element) {
  2941. QUnit.test('htmlImage2DataUrl2 async', assert => {
  2942. assert.ok(!$(element).html().match(/chat-demo-avatar/), source2)
  2943. assert.ok($(element).get(0).outerHTML.match(/^\<img src=\"data:image\/png;base64,/), source2)
  2944. assert.ok($(element).attr('style'), 'max-width: 100%;')
  2945. });
  2946. }
  2947. var htmlImage2DataUrlTest2Fail = function() {
  2948. QUnit.test('htmlImage2DataUrl2 async', assert => {
  2949. assert.ok(false, 'fail callback is exectuted!')
  2950. });
  2951. }
  2952. // Gitlab Issue #3538
  2953. // Jpeg images should convert to jpegs
  2954. // This functionality uses alt attribute present in img tag to get file type
  2955. // if alt attribute is missing then it will default to image/png
  2956. var jpegImageSource = '<img src="/assets/images/8000x300.jpg" alt="test.jpeg">jpeg image'
  2957. $('#jpegImage').html(jpegImageSource)
  2958. var htmlImage2DataUrlTest3 = function() {
  2959. QUnit.test("htmlImage2DataUrl3 async", assert => {
  2960. var result = App.Utils.htmlImage2DataUrl(jpegImageSource)
  2961. assert.ok(result.match(/jpeg image/), jpegImageSource)
  2962. assert.ok(result.match(/^\<img src=\"data:image\/jpeg;base64,/), jpegImageSource)
  2963. });
  2964. }
  2965. $('#jpegImage img').one('load', htmlImage2DataUrlTest3)
  2966. var pngImageSource = '<img src="/assets/images/1000x1000.png" alt="test.png">png image'
  2967. $('#pngImage').html(pngImageSource)
  2968. var htmlImage2DataUrlTest4 = function() {
  2969. QUnit.test("htmlImage2DataUrl4 async", assert => {
  2970. var result = App.Utils.htmlImage2DataUrl(pngImageSource)
  2971. assert.ok(result.match(/png image/), pngImageSource)
  2972. assert.ok(result.match(/^\<img src=\"data:image\/png;base64,/), pngImageSource)
  2973. });
  2974. }
  2975. $('#pngImage img').one('load', htmlImage2DataUrlTest4)
  2976. var jpegImageSourceWithoutAlt = '<img src="/assets/images/8000x300.jpg">jpeg image'
  2977. $('#jpegImage2').html(jpegImageSourceWithoutAlt)
  2978. var htmlImage2DataUrlTest5 = function() {
  2979. QUnit.test("htmlImage2DataUrl5 async", assert => {
  2980. var result = App.Utils.htmlImage2DataUrl(jpegImageSourceWithoutAlt)
  2981. assert.ok(result.match(/jpeg image/), jpegImageSourceWithoutAlt)
  2982. assert.ok(result.match(/^\<img src=\"data:image\/png;base64,/), jpegImageSourceWithoutAlt)
  2983. });
  2984. }
  2985. $('#jpegImage2 img').one('load', htmlImage2DataUrlTest5)
  2986. App.Utils.htmlImage2DataUrlAsyncInline($('#image2data2'), {success: htmlImage2DataUrlTest2Success, fail: htmlImage2DataUrlTest2Fail})
  2987. }
  2988. QUnit.test('App.Utils.baseUrl()', assert => {
  2989. configGetBackup = App.Config.get
  2990. // When FQDN is undefined or null,
  2991. // expect @baseUrl() to return window.location.origin
  2992. App.Config.get = function(key) { return undefined }
  2993. assert.equal(App.Utils.baseUrl(), window.location.origin, 'with undefined FQDN')
  2994. App.Config.get = function(key) { return null }
  2995. assert.equal(App.Utils.baseUrl(), window.location.origin, 'with null FQDN')
  2996. // When FQDN is zammad.example.com,
  2997. // expect @baseUrl() to return window.location.origin
  2998. App.Config.get = function(key) {
  2999. if (key === 'fqdn') {
  3000. return 'zammad.example.com'
  3001. }
  3002. }
  3003. assert.equal(App.Utils.baseUrl(), window.location.origin, 'with FQDN zammad.example.com')
  3004. // Otherwise,
  3005. // expect @baseUrl() to return FQDN with current HTTP(S) scheme
  3006. App.Config.get = function(key) {
  3007. if (key === 'fqdn') {
  3008. return 'foo.zammad.com'
  3009. } else if (key === 'http_type') {
  3010. return 'https'
  3011. }
  3012. }
  3013. assert.equal(App.Utils.baseUrl(), 'https://foo.zammad.com', 'with any other FQDN (and https scheme)')
  3014. App.Config.get = function(key) {
  3015. if (key === 'fqdn') {
  3016. return 'bar.zammad.com'
  3017. } else if (key === 'http_type') {
  3018. return 'http'
  3019. }
  3020. }
  3021. assert.equal(App.Utils.baseUrl(), 'http://bar.zammad.com', 'with any other FQDN (and http scheme)')
  3022. App.Config.get = configGetBackup
  3023. });
  3024. QUnit.test('App.Utils.joinUrlComponents()', assert => {
  3025. // When given a list of strings,
  3026. // expect @joinUrlComponents() to join them with slashes
  3027. assert.equal(App.Utils.joinUrlComponents('foo', 'bar', 'baz'), 'foo/bar/baz', 'with a destructured list of strings')
  3028. // When given an array of strings,
  3029. // expect @joinUrlComponents() to join them with slashes
  3030. assert.equal(App.Utils.joinUrlComponents(['foo', 'bar', 'baz']), 'foo/bar/baz', 'with an array of strings')
  3031. // When given a list of many types,
  3032. // expect @joinUrlComponents() to join their string representations with slashes
  3033. 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')
  3034. // When given a list including null or undefined,
  3035. // expect @joinUrlComponents() to filter them out of the results before joining the rest with slashes
  3036. assert.equal(App.Utils.joinUrlComponents('foo', undefined, 'bar', null, 'baz'), 'foo/bar/baz', 'with a list including null or undefined')
  3037. });
  3038. QUnit.test('App.Utils.clipboardHtmlIsWithText()', assert => {
  3039. // no content with text
  3040. assert.equal(App.Utils.clipboardHtmlIsWithText('<div></div>'), false)
  3041. assert.equal(App.Utils.clipboardHtmlIsWithText('<div> </div>'), false)
  3042. assert.equal(App.Utils.clipboardHtmlIsWithText('<div><img src="test.jpg"/></div>'), false)
  3043. assert.equal(App.Utils.clipboardHtmlIsWithText('<div><!-- some comment --></div>'), false)
  3044. assert.equal(App.Utils.clipboardHtmlIsWithText('<div><!-- some comment --> </div>'), false)
  3045. assert.equal(App.Utils.clipboardHtmlIsWithText("<div><!-- some comment --> \n </div>"), false)
  3046. // content with text
  3047. assert.equal(App.Utils.clipboardHtmlIsWithText('test'), true)
  3048. assert.equal(App.Utils.clipboardHtmlIsWithText('<div>test</div>'), true)
  3049. assert.equal(App.Utils.clipboardHtmlIsWithText('<meta http-equiv="content-type" content="text/html; charset=utf-8">sometext'), true)
  3050. });
  3051. QUnit.test('App.Utils.clipboardHtmlInsertPreperation()', assert => {
  3052. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div></div>', {}), '')
  3053. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div> </div>', {}), ' ')
  3054. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><img src="test.jpg"/></div>', {}), '<img src="test.jpg">')
  3055. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><!-- some comment --></div>', {}), '')
  3056. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><!-- some comment --> </div>', {}), ' ')
  3057. assert.equal(App.Utils.clipboardHtmlInsertPreperation("<div><!-- some comment --> \n </div>", {}), " \n ")
  3058. assert.equal(App.Utils.clipboardHtmlInsertPreperation('test', {}), 'test')
  3059. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div>test</div>', {}), 'test')
  3060. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<meta http-equiv="content-type" content="text/html; charset=utf-8">sometext', {}), '<div>sometext</div>')
  3061. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><b>test</b> 123</div>', { mode: 'textonly' }), 'test 123')
  3062. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><b>test</b><br> 123</div>', { mode: 'textonly' }), 'test 123')
  3063. assert.equal(App.Utils.clipboardHtmlInsertPreperation('<div><b>test</b><br> 123</div>', { mode: 'textonly', multiline: true }), 'test<br> 123')
  3064. });
  3065. QUnit.test('App.Utils.signatureIdentifyByHtmlHelper()', assert => {
  3066. result = App.Utils.signatureIdentifyByHtmlHelper("&lt;script&gt;alert('fish2');&lt;/script&gt;<blockquote></blockquote>")
  3067. assert.equal(result, "&lt;script&gt;alert('fish2');&lt;/script&gt;<span class=\"js-signatureMarker\"></span><blockquote></blockquote>", 'signatureIdentifyByHtmlHelper does not reactivate alert')
  3068. });
  3069. QUnit.test("#safeParseHtml", assert => {
  3070. var unwrap = input => $('<div>').html(input)[0].innerHTML
  3071. var html = "<div>test 123 </div>"
  3072. var result = App.Utils.safeParseHtml(html)
  3073. var should = html
  3074. assert.equal(unwrap(result), html)
  3075. // test if, according to jQuery, invalid HTML does not cause a a crash
  3076. // https://github.com/zammad/zammad/issues/3393
  3077. html = "<td></td><table></table><div>test 123 </div>"
  3078. should = "<table></table><div>test 123 </div>"
  3079. result = App.Utils.safeParseHtml(html)
  3080. assert.equal(unwrap(result), should)
  3081. })