How to use Diff method in backstopjs

Best JavaScript code snippet using backstopjs

diff_match_patch_test.py

Source:diff_match_patch_test.py Github

copy

Full Screen

1#!/usr/bin/python32"""Test harness for diff_match_patch.py3Copyright 2006 Google Inc.4http://code.google.com/p/google-diff-match-patch/5Licensed under the Apache License, Version 2.0 (the "License");6you may not use this file except in compliance with the License.7You may obtain a copy of the License at8  http://www.apache.org/licenses/LICENSE-2.09Unless required by applicable law or agreed to in writing, software10distributed under the License is distributed on an "AS IS" BASIS,11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12See the License for the specific language governing permissions and13limitations under the License.14"""15import imp16import sys17import time18import unittest19import diff_match_patch as dmp_module20# Force a module reload.  Allows one to edit the DMP module and rerun the tests21# without leaving the Python interpreter.22imp.reload(dmp_module)23class DiffMatchPatchTest(unittest.TestCase):24  def setUp(self):25    "Test harness for dmp_module."26    self.dmp = dmp_module.diff_match_patch()27  def diff_rebuildtexts(self, diffs):28    # Construct the two texts which made up the diff originally.29    text1 = ""30    text2 = ""31    for x in range(0, len(diffs)):32      if diffs[x][0] != dmp_module.diff_match_patch.DIFF_INSERT:33        text1 += diffs[x][1]34      if diffs[x][0] != dmp_module.diff_match_patch.DIFF_DELETE:35        text2 += diffs[x][1]36    return (text1, text2)37class DiffTest(DiffMatchPatchTest):38  """DIFF TEST FUNCTIONS"""39  def testDiffCommonPrefix(self):40    # Detect any common prefix.41    # Null case.42    self.assertEqual(0, self.dmp.diff_commonPrefix("abc", "xyz"))43    # Non-null case.44    self.assertEqual(4, self.dmp.diff_commonPrefix("1234abcdef", "1234xyz"))45    # Whole case.46    self.assertEqual(4, self.dmp.diff_commonPrefix("1234", "1234xyz"))47  def testDiffCommonSuffix(self):48    # Detect any common suffix.49    # Null case.50    self.assertEqual(0, self.dmp.diff_commonSuffix("abc", "xyz"))51    # Non-null case.52    self.assertEqual(4, self.dmp.diff_commonSuffix("abcdef1234", "xyz1234"))53    # Whole case.54    self.assertEqual(4, self.dmp.diff_commonSuffix("1234", "xyz1234"))55  def testDiffCommonOverlap(self):56    # Null case.57    self.assertEqual(0, self.dmp.diff_commonOverlap("", "abcd"))58    # Whole case.59    self.assertEqual(3, self.dmp.diff_commonOverlap("abc", "abcd"))60    # No overlap.61    self.assertEqual(0, self.dmp.diff_commonOverlap("123456", "abcd"))62    # Overlap.63    self.assertEqual(3, self.dmp.diff_commonOverlap("123456xxx", "xxxabcd"))64    # Unicode.65    # Some overly clever languages (C#) may treat ligatures as equal to their66    # component letters.  E.g. U+FB01 == 'fi'67    self.assertEqual(0, self.dmp.diff_commonOverlap("fi", "\ufb01i"))68  def testDiffHalfMatch(self):69    # Detect a halfmatch.70    self.dmp.Diff_Timeout = 171    # No match.72    self.assertEqual(None, self.dmp.diff_halfMatch("1234567890", "abcdef"))73    self.assertEqual(None, self.dmp.diff_halfMatch("12345", "23"))74    # Single Match.75    self.assertEqual(("12", "90", "a", "z", "345678"), self.dmp.diff_halfMatch("1234567890", "a345678z"))76    self.assertEqual(("a", "z", "12", "90", "345678"), self.dmp.diff_halfMatch("a345678z", "1234567890"))77    self.assertEqual(("abc", "z", "1234", "0", "56789"), self.dmp.diff_halfMatch("abc56789z", "1234567890"))78    self.assertEqual(("a", "xyz", "1", "7890", "23456"), self.dmp.diff_halfMatch("a23456xyz", "1234567890"))79    # Multiple Matches.80    self.assertEqual(("12123", "123121", "a", "z", "1234123451234"), self.dmp.diff_halfMatch("121231234123451234123121", "a1234123451234z"))81    self.assertEqual(("", "-=-=-=-=-=", "x", "", "x-=-=-=-=-=-=-="), self.dmp.diff_halfMatch("x-=-=-=-=-=-=-=-=-=-=-=-=", "xx-=-=-=-=-=-=-="))82    self.assertEqual(("-=-=-=-=-=", "", "", "y", "-=-=-=-=-=-=-=y"), self.dmp.diff_halfMatch("-=-=-=-=-=-=-=-=-=-=-=-=y", "-=-=-=-=-=-=-=yy"))83    # Non-optimal halfmatch.84    # Optimal diff would be -q+x=H-i+e=lloHe+Hu=llo-Hew+y not -qHillo+x=HelloHe-w+Hulloy85    self.assertEqual(("qHillo", "w", "x", "Hulloy", "HelloHe"), self.dmp.diff_halfMatch("qHilloHelloHew", "xHelloHeHulloy"))86    # Optimal no halfmatch.87    self.dmp.Diff_Timeout = 088    self.assertEqual(None, self.dmp.diff_halfMatch("qHilloHelloHew", "xHelloHeHulloy"))89  def testDiffLinesToChars(self):90    # Convert lines down to characters.91    self.assertEqual(("\x01\x02\x01", "\x02\x01\x02", ["", "alpha\n", "beta\n"]), self.dmp.diff_linesToChars("alpha\nbeta\nalpha\n", "beta\nalpha\nbeta\n"))92    self.assertEqual(("", "\x01\x02\x03\x03", ["", "alpha\r\n", "beta\r\n", "\r\n"]), self.dmp.diff_linesToChars("", "alpha\r\nbeta\r\n\r\n\r\n"))93    self.assertEqual(("\x01", "\x02", ["", "a", "b"]), self.dmp.diff_linesToChars("a", "b"))94    # More than 256 to reveal any 8-bit limitations.95    n = 30096    lineList = []97    charList = []98    for x in range(1, n + 1):99      lineList.append(str(x) + "\n")100      charList.append(chr(x))101    self.assertEqual(n, len(lineList))102    lines = "".join(lineList)103    chars = "".join(charList)104    self.assertEqual(n, len(chars))105    lineList.insert(0, "")106    self.assertEqual((chars, "", lineList), self.dmp.diff_linesToChars(lines, ""))107  def testDiffCharsToLines(self):108    # Convert chars up to lines.109    diffs = [(self.dmp.DIFF_EQUAL, "\x01\x02\x01"), (self.dmp.DIFF_INSERT, "\x02\x01\x02")]110    self.dmp.diff_charsToLines(diffs, ["", "alpha\n", "beta\n"])111    self.assertEqual([(self.dmp.DIFF_EQUAL, "alpha\nbeta\nalpha\n"), (self.dmp.DIFF_INSERT, "beta\nalpha\nbeta\n")], diffs)112    # More than 256 to reveal any 8-bit limitations.113    n = 300114    lineList = []115    charList = []116    for x in range(1, n + 1):117      lineList.append(str(x) + "\n")118      charList.append(chr(x))119    self.assertEqual(n, len(lineList))120    lines = "".join(lineList)121    chars = "".join(charList)122    self.assertEqual(n, len(chars))123    lineList.insert(0, "")124    diffs = [(self.dmp.DIFF_DELETE, chars)]125    self.dmp.diff_charsToLines(diffs, lineList)126    self.assertEqual([(self.dmp.DIFF_DELETE, lines)], diffs)127  def testDiffCleanupMerge(self):128    # Cleanup a messy diff.129    # Null case.130    diffs = []131    self.dmp.diff_cleanupMerge(diffs)132    self.assertEqual([], diffs)133    # No change case.134    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_INSERT, "c")]135    self.dmp.diff_cleanupMerge(diffs)136    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_INSERT, "c")], diffs)137    # Merge equalities.138    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_EQUAL, "c")]139    self.dmp.diff_cleanupMerge(diffs)140    self.assertEqual([(self.dmp.DIFF_EQUAL, "abc")], diffs)141    # Merge deletions.142    diffs = [(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_DELETE, "c")]143    self.dmp.diff_cleanupMerge(diffs)144    self.assertEqual([(self.dmp.DIFF_DELETE, "abc")], diffs)145    # Merge insertions.146    diffs = [(self.dmp.DIFF_INSERT, "a"), (self.dmp.DIFF_INSERT, "b"), (self.dmp.DIFF_INSERT, "c")]147    self.dmp.diff_cleanupMerge(diffs)148    self.assertEqual([(self.dmp.DIFF_INSERT, "abc")], diffs)149    # Merge interweave.150    diffs = [(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "b"), (self.dmp.DIFF_DELETE, "c"), (self.dmp.DIFF_INSERT, "d"), (self.dmp.DIFF_EQUAL, "e"), (self.dmp.DIFF_EQUAL, "f")]151    self.dmp.diff_cleanupMerge(diffs)152    self.assertEqual([(self.dmp.DIFF_DELETE, "ac"), (self.dmp.DIFF_INSERT, "bd"), (self.dmp.DIFF_EQUAL, "ef")], diffs)153    # Prefix and suffix detection.154    diffs = [(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "abc"), (self.dmp.DIFF_DELETE, "dc")]155    self.dmp.diff_cleanupMerge(diffs)156    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "d"), (self.dmp.DIFF_INSERT, "b"), (self.dmp.DIFF_EQUAL, "c")], diffs)157    # Prefix and suffix detection with equalities.158    diffs = [(self.dmp.DIFF_EQUAL, "x"), (self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "abc"), (self.dmp.DIFF_DELETE, "dc"), (self.dmp.DIFF_EQUAL, "y")]159    self.dmp.diff_cleanupMerge(diffs)160    self.assertEqual([(self.dmp.DIFF_EQUAL, "xa"), (self.dmp.DIFF_DELETE, "d"), (self.dmp.DIFF_INSERT, "b"), (self.dmp.DIFF_EQUAL, "cy")], diffs)161    # Slide edit left.162    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_INSERT, "ba"), (self.dmp.DIFF_EQUAL, "c")]163    self.dmp.diff_cleanupMerge(diffs)164    self.assertEqual([(self.dmp.DIFF_INSERT, "ab"), (self.dmp.DIFF_EQUAL, "ac")], diffs)165    # Slide edit right.166    diffs = [(self.dmp.DIFF_EQUAL, "c"), (self.dmp.DIFF_INSERT, "ab"), (self.dmp.DIFF_EQUAL, "a")]167    self.dmp.diff_cleanupMerge(diffs)168    self.assertEqual([(self.dmp.DIFF_EQUAL, "ca"), (self.dmp.DIFF_INSERT, "ba")], diffs)169    # Slide edit left recursive.170    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_EQUAL, "c"), (self.dmp.DIFF_DELETE, "ac"), (self.dmp.DIFF_EQUAL, "x")]171    self.dmp.diff_cleanupMerge(diffs)172    self.assertEqual([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_EQUAL, "acx")], diffs)173    # Slide edit right recursive.174    diffs = [(self.dmp.DIFF_EQUAL, "x"), (self.dmp.DIFF_DELETE, "ca"), (self.dmp.DIFF_EQUAL, "c"), (self.dmp.DIFF_DELETE, "b"), (self.dmp.DIFF_EQUAL, "a")]175    self.dmp.diff_cleanupMerge(diffs)176    self.assertEqual([(self.dmp.DIFF_EQUAL, "xca"), (self.dmp.DIFF_DELETE, "cba")], diffs)177  def testDiffCleanupSemanticLossless(self):178    # Slide diffs to match logical boundaries.179    # Null case.180    diffs = []181    self.dmp.diff_cleanupSemanticLossless(diffs)182    self.assertEqual([], diffs)183    # Blank lines.184    diffs = [(self.dmp.DIFF_EQUAL, "AAA\r\n\r\nBBB"), (self.dmp.DIFF_INSERT, "\r\nDDD\r\n\r\nBBB"), (self.dmp.DIFF_EQUAL, "\r\nEEE")]185    self.dmp.diff_cleanupSemanticLossless(diffs)186    self.assertEqual([(self.dmp.DIFF_EQUAL, "AAA\r\n\r\n"), (self.dmp.DIFF_INSERT, "BBB\r\nDDD\r\n\r\n"), (self.dmp.DIFF_EQUAL, "BBB\r\nEEE")], diffs)187    # Line boundaries.188    diffs = [(self.dmp.DIFF_EQUAL, "AAA\r\nBBB"), (self.dmp.DIFF_INSERT, " DDD\r\nBBB"), (self.dmp.DIFF_EQUAL, " EEE")]189    self.dmp.diff_cleanupSemanticLossless(diffs)190    self.assertEqual([(self.dmp.DIFF_EQUAL, "AAA\r\n"), (self.dmp.DIFF_INSERT, "BBB DDD\r\n"), (self.dmp.DIFF_EQUAL, "BBB EEE")], diffs)191    # Word boundaries.192    diffs = [(self.dmp.DIFF_EQUAL, "The c"), (self.dmp.DIFF_INSERT, "ow and the c"), (self.dmp.DIFF_EQUAL, "at.")]193    self.dmp.diff_cleanupSemanticLossless(diffs)194    self.assertEqual([(self.dmp.DIFF_EQUAL, "The "), (self.dmp.DIFF_INSERT, "cow and the "), (self.dmp.DIFF_EQUAL, "cat.")], diffs)195    # Alphanumeric boundaries.196    diffs = [(self.dmp.DIFF_EQUAL, "The-c"), (self.dmp.DIFF_INSERT, "ow-and-the-c"), (self.dmp.DIFF_EQUAL, "at.")]197    self.dmp.diff_cleanupSemanticLossless(diffs)198    self.assertEqual([(self.dmp.DIFF_EQUAL, "The-"), (self.dmp.DIFF_INSERT, "cow-and-the-"), (self.dmp.DIFF_EQUAL, "cat.")], diffs)199    # Hitting the start.200    diffs = [(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_EQUAL, "ax")]201    self.dmp.diff_cleanupSemanticLossless(diffs)202    self.assertEqual([(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_EQUAL, "aax")], diffs)203    # Hitting the end.204    diffs = [(self.dmp.DIFF_EQUAL, "xa"), (self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_EQUAL, "a")]205    self.dmp.diff_cleanupSemanticLossless(diffs)206    self.assertEqual([(self.dmp.DIFF_EQUAL, "xaa"), (self.dmp.DIFF_DELETE, "a")], diffs)207    # Sentence boundaries.208    diffs = [(self.dmp.DIFF_EQUAL, "The xxx. The "), (self.dmp.DIFF_INSERT, "zzz. The "), (self.dmp.DIFF_EQUAL, "yyy.")]209    self.dmp.diff_cleanupSemanticLossless(diffs)210    self.assertEqual([(self.dmp.DIFF_EQUAL, "The xxx."), (self.dmp.DIFF_INSERT, " The zzz."), (self.dmp.DIFF_EQUAL, " The yyy.")], diffs)211  def testDiffCleanupSemantic(self):212    # Cleanup semantically trivial equalities.213    # Null case.214    diffs = []215    self.dmp.diff_cleanupSemantic(diffs)216    self.assertEqual([], diffs)217    # No elimination #1.218    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "cd"), (self.dmp.DIFF_EQUAL, "12"), (self.dmp.DIFF_DELETE, "e")]219    self.dmp.diff_cleanupSemantic(diffs)220    self.assertEqual([(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "cd"), (self.dmp.DIFF_EQUAL, "12"), (self.dmp.DIFF_DELETE, "e")], diffs)221    # No elimination #2.222    diffs = [(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "ABC"), (self.dmp.DIFF_EQUAL, "1234"), (self.dmp.DIFF_DELETE, "wxyz")]223    self.dmp.diff_cleanupSemantic(diffs)224    self.assertEqual([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "ABC"), (self.dmp.DIFF_EQUAL, "1234"), (self.dmp.DIFF_DELETE, "wxyz")], diffs)225    # Simple elimination.226    diffs = [(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_DELETE, "c")]227    self.dmp.diff_cleanupSemantic(diffs)228    self.assertEqual([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "b")], diffs)229    # Backpass elimination.230    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_EQUAL, "cd"), (self.dmp.DIFF_DELETE, "e"), (self.dmp.DIFF_EQUAL, "f"), (self.dmp.DIFF_INSERT, "g")]231    self.dmp.diff_cleanupSemantic(diffs)232    self.assertEqual([(self.dmp.DIFF_DELETE, "abcdef"), (self.dmp.DIFF_INSERT, "cdfg")], diffs)233    # Multiple eliminations.234    diffs = [(self.dmp.DIFF_INSERT, "1"), (self.dmp.DIFF_EQUAL, "A"), (self.dmp.DIFF_DELETE, "B"), (self.dmp.DIFF_INSERT, "2"), (self.dmp.DIFF_EQUAL, "_"), (self.dmp.DIFF_INSERT, "1"), (self.dmp.DIFF_EQUAL, "A"), (self.dmp.DIFF_DELETE, "B"), (self.dmp.DIFF_INSERT, "2")]235    self.dmp.diff_cleanupSemantic(diffs)236    self.assertEqual([(self.dmp.DIFF_DELETE, "AB_AB"), (self.dmp.DIFF_INSERT, "1A2_1A2")], diffs)237    # Word boundaries.238    diffs = [(self.dmp.DIFF_EQUAL, "The c"), (self.dmp.DIFF_DELETE, "ow and the c"), (self.dmp.DIFF_EQUAL, "at.")]239    self.dmp.diff_cleanupSemantic(diffs)240    self.assertEqual([(self.dmp.DIFF_EQUAL, "The "), (self.dmp.DIFF_DELETE, "cow and the "), (self.dmp.DIFF_EQUAL, "cat.")], diffs)241    # No overlap elimination.242    diffs = [(self.dmp.DIFF_DELETE, "abcxx"), (self.dmp.DIFF_INSERT, "xxdef")]243    self.dmp.diff_cleanupSemantic(diffs)244    self.assertEqual([(self.dmp.DIFF_DELETE, "abcxx"), (self.dmp.DIFF_INSERT, "xxdef")], diffs)245    # Overlap elimination.246    diffs = [(self.dmp.DIFF_DELETE, "abcxxx"), (self.dmp.DIFF_INSERT, "xxxdef")]247    self.dmp.diff_cleanupSemantic(diffs)248    self.assertEqual([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_EQUAL, "xxx"), (self.dmp.DIFF_INSERT, "def")], diffs)249    # Reverse overlap elimination.250    diffs = [(self.dmp.DIFF_DELETE, "xxxabc"), (self.dmp.DIFF_INSERT, "defxxx")]251    self.dmp.diff_cleanupSemantic(diffs)252    self.assertEqual([(self.dmp.DIFF_INSERT, "def"), (self.dmp.DIFF_EQUAL, "xxx"), (self.dmp.DIFF_DELETE, "abc")], diffs)253    # Two overlap eliminations.254    diffs = [(self.dmp.DIFF_DELETE, "abcd1212"), (self.dmp.DIFF_INSERT, "1212efghi"), (self.dmp.DIFF_EQUAL, "----"), (self.dmp.DIFF_DELETE, "A3"), (self.dmp.DIFF_INSERT, "3BC")]255    self.dmp.diff_cleanupSemantic(diffs)256    self.assertEqual([(self.dmp.DIFF_DELETE, "abcd"), (self.dmp.DIFF_EQUAL, "1212"), (self.dmp.DIFF_INSERT, "efghi"), (self.dmp.DIFF_EQUAL, "----"), (self.dmp.DIFF_DELETE, "A"), (self.dmp.DIFF_EQUAL, "3"), (self.dmp.DIFF_INSERT, "BC")], diffs)257  def testDiffCleanupEfficiency(self):258    # Cleanup operationally trivial equalities.259    self.dmp.Diff_EditCost = 4260    # Null case.261    diffs = []262    self.dmp.diff_cleanupEfficiency(diffs)263    self.assertEqual([], diffs)264    # No elimination.265    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "wxyz"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")]266    self.dmp.diff_cleanupEfficiency(diffs)267    self.assertEqual([(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "wxyz"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")], diffs)268    # Four-edit elimination.269    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "xyz"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")]270    self.dmp.diff_cleanupEfficiency(diffs)271    self.assertEqual([(self.dmp.DIFF_DELETE, "abxyzcd"), (self.dmp.DIFF_INSERT, "12xyz34")], diffs)272    # Three-edit elimination.273    diffs = [(self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "x"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")]274    self.dmp.diff_cleanupEfficiency(diffs)275    self.assertEqual([(self.dmp.DIFF_DELETE, "xcd"), (self.dmp.DIFF_INSERT, "12x34")], diffs)276    # Backpass elimination.277    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "xy"), (self.dmp.DIFF_INSERT, "34"), (self.dmp.DIFF_EQUAL, "z"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "56")]278    self.dmp.diff_cleanupEfficiency(diffs)279    self.assertEqual([(self.dmp.DIFF_DELETE, "abxyzcd"), (self.dmp.DIFF_INSERT, "12xy34z56")], diffs)280    # High cost elimination.281    self.dmp.Diff_EditCost = 5282    diffs = [(self.dmp.DIFF_DELETE, "ab"), (self.dmp.DIFF_INSERT, "12"), (self.dmp.DIFF_EQUAL, "wxyz"), (self.dmp.DIFF_DELETE, "cd"), (self.dmp.DIFF_INSERT, "34")]283    self.dmp.diff_cleanupEfficiency(diffs)284    self.assertEqual([(self.dmp.DIFF_DELETE, "abwxyzcd"), (self.dmp.DIFF_INSERT, "12wxyz34")], diffs)285    self.dmp.Diff_EditCost = 4286  def testDiffPrettyHtml(self):287    # Pretty print.288    diffs = [(self.dmp.DIFF_EQUAL, "a\n"), (self.dmp.DIFF_DELETE, "<B>b</B>"), (self.dmp.DIFF_INSERT, "c&d")]289    self.assertEqual("<span>a&para;<br></span><del style=\"background:#ffe6e6;\">&lt;B&gt;b&lt;/B&gt;</del><ins style=\"background:#e6ffe6;\">c&amp;d</ins>", self.dmp.diff_prettyHtml(diffs))290  def testDiffText(self):291    # Compute the source and destination texts.292    diffs = [(self.dmp.DIFF_EQUAL, "jump"), (self.dmp.DIFF_DELETE, "s"), (self.dmp.DIFF_INSERT, "ed"), (self.dmp.DIFF_EQUAL, " over "), (self.dmp.DIFF_DELETE, "the"), (self.dmp.DIFF_INSERT, "a"), (self.dmp.DIFF_EQUAL, " lazy")]293    self.assertEqual("jumps over the lazy", self.dmp.diff_text1(diffs))294    self.assertEqual("jumped over a lazy", self.dmp.diff_text2(diffs))295  def testDiffDelta(self):296    # Convert a diff into delta string.297    diffs = [(self.dmp.DIFF_EQUAL, "jump"), (self.dmp.DIFF_DELETE, "s"), (self.dmp.DIFF_INSERT, "ed"), (self.dmp.DIFF_EQUAL, " over "), (self.dmp.DIFF_DELETE, "the"), (self.dmp.DIFF_INSERT, "a"), (self.dmp.DIFF_EQUAL, " lazy"), (self.dmp.DIFF_INSERT, "old dog")]298    text1 = self.dmp.diff_text1(diffs)299    self.assertEqual("jumps over the lazy", text1)300    delta = self.dmp.diff_toDelta(diffs)301    self.assertEqual("=4\t-1\t+ed\t=6\t-3\t+a\t=5\t+old dog", delta)302    # Convert delta string into a diff.303    self.assertEqual(diffs, self.dmp.diff_fromDelta(text1, delta))304    # Generates error (19 != 20).305    try:306      self.dmp.diff_fromDelta(text1 + "x", delta)307      self.assertFalse(True)308    except ValueError:309      # Exception expected.310      pass311    # Generates error (19 != 18).312    try:313      self.dmp.diff_fromDelta(text1[1:], delta)314      self.assertFalse(True)315    except ValueError:316      # Exception expected.317      pass318    # Generates error (%c3%xy invalid Unicode).319    # Note: Python 3 can decode this.320    #try:321    #  self.dmp.diff_fromDelta("", "+%c3xy")322    #  self.assertFalse(True)323    #except ValueError:324    #  # Exception expected.325    #  pass326    # Test deltas with special characters.327    diffs = [(self.dmp.DIFF_EQUAL, "\u0680 \x00 \t %"), (self.dmp.DIFF_DELETE, "\u0681 \x01 \n ^"), (self.dmp.DIFF_INSERT, "\u0682 \x02 \\ |")]328    text1 = self.dmp.diff_text1(diffs)329    self.assertEqual("\u0680 \x00 \t %\u0681 \x01 \n ^", text1)330    delta = self.dmp.diff_toDelta(diffs)331    self.assertEqual("=7\t-7\t+%DA%82 %02 %5C %7C", delta)332    # Convert delta string into a diff.333    self.assertEqual(diffs, self.dmp.diff_fromDelta(text1, delta))334    # Verify pool of unchanged characters.335    diffs = [(self.dmp.DIFF_INSERT, "A-Z a-z 0-9 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , # ")]336    text2 = self.dmp.diff_text2(diffs)337    self.assertEqual("A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ", text2)338    delta = self.dmp.diff_toDelta(diffs)339    self.assertEqual("+A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ", delta)340    # Convert delta string into a diff.341    self.assertEqual(diffs, self.dmp.diff_fromDelta("", delta))342  def testDiffXIndex(self):343    # Translate a location in text1 to text2.344    self.assertEqual(5, self.dmp.diff_xIndex([(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "1234"), (self.dmp.DIFF_EQUAL, "xyz")], 2))345    # Translation on deletion.346    self.assertEqual(1, self.dmp.diff_xIndex([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "1234"), (self.dmp.DIFF_EQUAL, "xyz")], 3))347  def testDiffLevenshtein(self):348    # Levenshtein with trailing equality.349    self.assertEqual(4, self.dmp.diff_levenshtein([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "1234"), (self.dmp.DIFF_EQUAL, "xyz")]))350    # Levenshtein with leading equality.351    self.assertEqual(4, self.dmp.diff_levenshtein([(self.dmp.DIFF_EQUAL, "xyz"), (self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_INSERT, "1234")]))352    # Levenshtein with middle equality.353    self.assertEqual(7, self.dmp.diff_levenshtein([(self.dmp.DIFF_DELETE, "abc"), (self.dmp.DIFF_EQUAL, "xyz"), (self.dmp.DIFF_INSERT, "1234")]))354  def testDiffBisect(self):355    # Normal.356    a = "cat"357    b = "map"358    # Since the resulting diff hasn't been normalized, it would be ok if359    # the insertion and deletion pairs are swapped.360    # If the order changes, tweak this test as required.361    self.assertEqual([(self.dmp.DIFF_DELETE, "c"), (self.dmp.DIFF_INSERT, "m"), (self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "t"), (self.dmp.DIFF_INSERT, "p")], self.dmp.diff_bisect(a, b, sys.maxsize))362    # Timeout.363    self.assertEqual([(self.dmp.DIFF_DELETE, "cat"), (self.dmp.DIFF_INSERT, "map")], self.dmp.diff_bisect(a, b, 0))364  def testDiffMain(self):365    # Perform a trivial diff.366    # Null case.367    self.assertEqual([], self.dmp.diff_main("", "", False))368    # Equality.369    self.assertEqual([(self.dmp.DIFF_EQUAL, "abc")], self.dmp.diff_main("abc", "abc", False))370    # Simple insertion.371    self.assertEqual([(self.dmp.DIFF_EQUAL, "ab"), (self.dmp.DIFF_INSERT, "123"), (self.dmp.DIFF_EQUAL, "c")], self.dmp.diff_main("abc", "ab123c", False))372    # Simple deletion.373    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "123"), (self.dmp.DIFF_EQUAL, "bc")], self.dmp.diff_main("a123bc", "abc", False))374    # Two insertions.375    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_INSERT, "123"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_INSERT, "456"), (self.dmp.DIFF_EQUAL, "c")], self.dmp.diff_main("abc", "a123b456c", False))376    # Two deletions.377    self.assertEqual([(self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "123"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_DELETE, "456"), (self.dmp.DIFF_EQUAL, "c")], self.dmp.diff_main("a123b456c", "abc", False))378    # Perform a real diff.379    # Switch off the timeout.380    self.dmp.Diff_Timeout = 0381    # Simple cases.382    self.assertEqual([(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "b")], self.dmp.diff_main("a", "b", False))383    self.assertEqual([(self.dmp.DIFF_DELETE, "Apple"), (self.dmp.DIFF_INSERT, "Banana"), (self.dmp.DIFF_EQUAL, "s are a"), (self.dmp.DIFF_INSERT, "lso"), (self.dmp.DIFF_EQUAL, " fruit.")], self.dmp.diff_main("Apples are a fruit.", "Bananas are also fruit.", False))384    self.assertEqual([(self.dmp.DIFF_DELETE, "a"), (self.dmp.DIFF_INSERT, "\u0680"), (self.dmp.DIFF_EQUAL, "x"), (self.dmp.DIFF_DELETE, "\t"), (self.dmp.DIFF_INSERT, "\x00")], self.dmp.diff_main("ax\t", "\u0680x\x00", False))385    # Overlaps.386    self.assertEqual([(self.dmp.DIFF_DELETE, "1"), (self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "y"), (self.dmp.DIFF_EQUAL, "b"), (self.dmp.DIFF_DELETE, "2"), (self.dmp.DIFF_INSERT, "xab")], self.dmp.diff_main("1ayb2", "abxab", False))387    self.assertEqual([(self.dmp.DIFF_INSERT, "xaxcx"), (self.dmp.DIFF_EQUAL, "abc"), (self.dmp.DIFF_DELETE, "y")], self.dmp.diff_main("abcy", "xaxcxabc", False))388    self.assertEqual([(self.dmp.DIFF_DELETE, "ABCD"), (self.dmp.DIFF_EQUAL, "a"), (self.dmp.DIFF_DELETE, "="), (self.dmp.DIFF_INSERT, "-"), (self.dmp.DIFF_EQUAL, "bcd"), (self.dmp.DIFF_DELETE, "="), (self.dmp.DIFF_INSERT, "-"), (self.dmp.DIFF_EQUAL, "efghijklmnopqrs"), (self.dmp.DIFF_DELETE, "EFGHIJKLMNOefg")], self.dmp.diff_main("ABCDa=bcd=efghijklmnopqrsEFGHIJKLMNOefg", "a-bcd-efghijklmnopqrs", False))389    # Large equality.390    self.assertEqual([(self.dmp.DIFF_INSERT, " "), (self.dmp.DIFF_EQUAL,"a"), (self.dmp.DIFF_INSERT,"nd"), (self.dmp.DIFF_EQUAL," [[Pennsylvania]]"), (self.dmp.DIFF_DELETE," and [[New")], self.dmp.diff_main("a [[Pennsylvania]] and [[New", " and [[Pennsylvania]]", False))391    # Timeout.392    self.dmp.Diff_Timeout = 0.1  # 100ms393    a = "`Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.\n"394    b = "I am the very model of a modern major general,\nI've information vegetable, animal, and mineral,\nI know the kings of England, and I quote the fights historical,\nFrom Marathon to Waterloo, in order categorical.\n"395    # Increase the text lengths by 1024 times to ensure a timeout.396    for x in range(10):397      a = a + a398      b = b + b399    startTime = time.time()400    self.dmp.diff_main(a, b)401    endTime = time.time()402    # Test that we took at least the timeout period.403    self.assertTrue(self.dmp.Diff_Timeout <= endTime - startTime)404    # Test that we didn't take forever (be forgiving).405    # Theoretically this test could fail very occasionally if the406    # OS task swaps or locks up for a second at the wrong moment.407    self.assertTrue(self.dmp.Diff_Timeout * 2 > endTime - startTime)408    self.dmp.Diff_Timeout = 0409    # Test the linemode speedup.410    # Must be long to pass the 100 char cutoff.411    # Simple line-mode.412    a = "1234567890\n" * 13413    b = "abcdefghij\n" * 13414    self.assertEqual(self.dmp.diff_main(a, b, False), self.dmp.diff_main(a, b, True))415    # Single line-mode.416    a = "1234567890" * 13417    b = "abcdefghij" * 13418    self.assertEqual(self.dmp.diff_main(a, b, False), self.dmp.diff_main(a, b, True))419    # Overlap line-mode.420    a = "1234567890\n" * 13421    b = "abcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n"422    texts_linemode = self.diff_rebuildtexts(self.dmp.diff_main(a, b, True))423    texts_textmode = self.diff_rebuildtexts(self.dmp.diff_main(a, b, False))424    self.assertEqual(texts_textmode, texts_linemode)425    # Test null inputs.426    try:427      self.dmp.diff_main(None, None)428      self.assertFalse(True)429    except ValueError:430      # Exception expected.431      pass432class MatchTest(DiffMatchPatchTest):433  """MATCH TEST FUNCTIONS"""434  def testMatchAlphabet(self):435    # Initialise the bitmasks for Bitap.436    self.assertEqual({"a":4, "b":2, "c":1}, self.dmp.match_alphabet("abc"))437    self.assertEqual({"a":37, "b":18, "c":8}, self.dmp.match_alphabet("abcaba"))438  def testMatchBitap(self):439    self.dmp.Match_Distance = 100440    self.dmp.Match_Threshold = 0.5441    # Exact matches.442    self.assertEqual(5, self.dmp.match_bitap("abcdefghijk", "fgh", 5))443    self.assertEqual(5, self.dmp.match_bitap("abcdefghijk", "fgh", 0))444    # Fuzzy matches.445    self.assertEqual(4, self.dmp.match_bitap("abcdefghijk", "efxhi", 0))446    self.assertEqual(2, self.dmp.match_bitap("abcdefghijk", "cdefxyhijk", 5))447    self.assertEqual(-1, self.dmp.match_bitap("abcdefghijk", "bxy", 1))448    # Overflow.449    self.assertEqual(2, self.dmp.match_bitap("123456789xx0", "3456789x0", 2))450    self.assertEqual(0, self.dmp.match_bitap("abcdef", "xxabc", 4))451    self.assertEqual(3, self.dmp.match_bitap("abcdef", "defyy", 4))452    self.assertEqual(0, self.dmp.match_bitap("abcdef", "xabcdefy", 0))453    # Threshold test.454    self.dmp.Match_Threshold = 0.4455    self.assertEqual(4, self.dmp.match_bitap("abcdefghijk", "efxyhi", 1))456    self.dmp.Match_Threshold = 0.3457    self.assertEqual(-1, self.dmp.match_bitap("abcdefghijk", "efxyhi", 1))458    self.dmp.Match_Threshold = 0.0459    self.assertEqual(1, self.dmp.match_bitap("abcdefghijk", "bcdef", 1))460    self.dmp.Match_Threshold = 0.5461    # Multiple select.462    self.assertEqual(0, self.dmp.match_bitap("abcdexyzabcde", "abccde", 3))463    self.assertEqual(8, self.dmp.match_bitap("abcdexyzabcde", "abccde", 5))464    # Distance test.465    self.dmp.Match_Distance = 10  # Strict location.466    self.assertEqual(-1, self.dmp.match_bitap("abcdefghijklmnopqrstuvwxyz", "abcdefg", 24))467    self.assertEqual(0, self.dmp.match_bitap("abcdefghijklmnopqrstuvwxyz", "abcdxxefg", 1))468    self.dmp.Match_Distance = 1000  # Loose location.469    self.assertEqual(0, self.dmp.match_bitap("abcdefghijklmnopqrstuvwxyz", "abcdefg", 24))470  def testMatchMain(self):471    # Full match.472    # Shortcut matches.473    self.assertEqual(0, self.dmp.match_main("abcdef", "abcdef", 1000))474    self.assertEqual(-1, self.dmp.match_main("", "abcdef", 1))475    self.assertEqual(3, self.dmp.match_main("abcdef", "", 3))476    self.assertEqual(3, self.dmp.match_main("abcdef", "de", 3))477    self.assertEqual(3, self.dmp.match_main("abcdef", "defy", 4))478    self.assertEqual(0, self.dmp.match_main("abcdef", "abcdefy", 0))479    # Complex match.480    self.dmp.Match_Threshold = 0.7481    self.assertEqual(4, self.dmp.match_main("I am the very model of a modern major general.", " that berry ", 5))482    self.dmp.Match_Threshold = 0.5483    # Test null inputs.484    try:485      self.dmp.match_main(None, None, 0)486      self.assertFalse(True)487    except ValueError:488      # Exception expected.489      pass490class PatchTest(DiffMatchPatchTest):491  """PATCH TEST FUNCTIONS"""492  def testPatchObj(self):493    # Patch Object.494    p = dmp_module.patch_obj()495    p.start1 = 20496    p.start2 = 21497    p.length1 = 18498    p.length2 = 17499    p.diffs = [(self.dmp.DIFF_EQUAL, "jump"), (self.dmp.DIFF_DELETE, "s"), (self.dmp.DIFF_INSERT, "ed"), (self.dmp.DIFF_EQUAL, " over "), (self.dmp.DIFF_DELETE, "the"), (self.dmp.DIFF_INSERT, "a"), (self.dmp.DIFF_EQUAL, "\nlaz")]500    strp = str(p)501    self.assertEqual("@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n %0Alaz\n", strp)502  def testPatchFromText(self):503    self.assertEqual([], self.dmp.patch_fromText(""))504    strp = "@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n %0Alaz\n"505    self.assertEqual(strp, str(self.dmp.patch_fromText(strp)[0]))506    self.assertEqual("@@ -1 +1 @@\n-a\n+b\n", str(self.dmp.patch_fromText("@@ -1 +1 @@\n-a\n+b\n")[0]))507    self.assertEqual("@@ -1,3 +0,0 @@\n-abc\n", str(self.dmp.patch_fromText("@@ -1,3 +0,0 @@\n-abc\n")[0]))508    self.assertEqual("@@ -0,0 +1,3 @@\n+abc\n", str(self.dmp.patch_fromText("@@ -0,0 +1,3 @@\n+abc\n")[0]))509    # Generates error.510    try:511      self.dmp.patch_fromText("Bad\nPatch\n")512      self.assertFalse(True)513    except ValueError:514      # Exception expected.515      pass516  def testPatchToText(self):517    strp = "@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n  laz\n"518    p = self.dmp.patch_fromText(strp)519    self.assertEqual(strp, self.dmp.patch_toText(p))520    strp = "@@ -1,9 +1,9 @@\n-f\n+F\n oo+fooba\n@@ -7,9 +7,9 @@\n obar\n-,\n+.\n tes\n"521    p = self.dmp.patch_fromText(strp)522    self.assertEqual(strp, self.dmp.patch_toText(p))523  def testPatchAddContext(self):524    self.dmp.Patch_Margin = 4525    p = self.dmp.patch_fromText("@@ -21,4 +21,10 @@\n-jump\n+somersault\n")[0]526    self.dmp.patch_addContext(p, "The quick brown fox jumps over the lazy dog.")527    self.assertEqual("@@ -17,12 +17,18 @@\n fox \n-jump\n+somersault\n s ov\n", str(p))528    # Same, but not enough trailing context.529    p = self.dmp.patch_fromText("@@ -21,4 +21,10 @@\n-jump\n+somersault\n")[0]530    self.dmp.patch_addContext(p, "The quick brown fox jumps.")531    self.assertEqual("@@ -17,10 +17,16 @@\n fox \n-jump\n+somersault\n s.\n", str(p))532    # Same, but not enough leading context.533    p = self.dmp.patch_fromText("@@ -3 +3,2 @@\n-e\n+at\n")[0]534    self.dmp.patch_addContext(p, "The quick brown fox jumps.")535    self.assertEqual("@@ -1,7 +1,8 @@\n Th\n-e\n+at\n  qui\n", str(p))536    # Same, but with ambiguity.537    p = self.dmp.patch_fromText("@@ -3 +3,2 @@\n-e\n+at\n")[0]538    self.dmp.patch_addContext(p, "The quick brown fox jumps.  The quick brown fox crashes.")539    self.assertEqual("@@ -1,27 +1,28 @@\n Th\n-e\n+at\n  quick brown fox jumps. \n", str(p))540  def testPatchMake(self):541    # Null case.542    patches = self.dmp.patch_make("", "")543    self.assertEqual("", self.dmp.patch_toText(patches))544    text1 = "The quick brown fox jumps over the lazy dog."545    text2 = "That quick brown fox jumped over a lazy dog."546    # Text2+Text1 inputs.547    expectedPatch = "@@ -1,8 +1,7 @@\n Th\n-at\n+e\n  qui\n@@ -21,17 +21,18 @@\n jump\n-ed\n+s\n  over \n-a\n+the\n  laz\n"548    # The second patch must be "-21,17 +21,18", not "-22,17 +21,18" due to rolling context.549    patches = self.dmp.patch_make(text2, text1)550    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))551    # Text1+Text2 inputs.552    expectedPatch = "@@ -1,11 +1,12 @@\n Th\n-e\n+at\n  quick b\n@@ -22,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n  laz\n"553    patches = self.dmp.patch_make(text1, text2)554    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))555    # Diff input.556    diffs = self.dmp.diff_main(text1, text2, False)557    patches = self.dmp.patch_make(diffs)558    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))559    # Text1+Diff inputs.560    patches = self.dmp.patch_make(text1, diffs)561    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))562    # Text1+Text2+Diff inputs (deprecated).563    patches = self.dmp.patch_make(text1, text2, diffs)564    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))565    # Character encoding.566    patches = self.dmp.patch_make("`1234567890-=[]\\;',./", "~!@#$%^&*()_+{}|:\"<>?")567    self.assertEqual("@@ -1,21 +1,21 @@\n-%601234567890-=%5B%5D%5C;',./\n+~!@#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\n", self.dmp.patch_toText(patches))568    # Character decoding.569    diffs = [(self.dmp.DIFF_DELETE, "`1234567890-=[]\\;',./"), (self.dmp.DIFF_INSERT, "~!@#$%^&*()_+{}|:\"<>?")]570    self.assertEqual(diffs, self.dmp.patch_fromText("@@ -1,21 +1,21 @@\n-%601234567890-=%5B%5D%5C;',./\n+~!@#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\n")[0].diffs)571    # Long string with repeats.572    text1 = ""573    for x in range(100):574      text1 += "abcdef"575    text2 = text1 + "123"576    expectedPatch = "@@ -573,28 +573,31 @@\n cdefabcdefabcdefabcdefabcdef\n+123\n"577    patches = self.dmp.patch_make(text1, text2)578    self.assertEqual(expectedPatch, self.dmp.patch_toText(patches))579    # Test null inputs.580    try:581      self.dmp.patch_make(None, None)582      self.assertFalse(True)583    except ValueError:584      # Exception expected.585      pass586  def testPatchSplitMax(self):587    # Assumes that Match_MaxBits is 32.588    patches = self.dmp.patch_make("abcdefghijklmnopqrstuvwxyz01234567890", "XabXcdXefXghXijXklXmnXopXqrXstXuvXwxXyzX01X23X45X67X89X0")589    self.dmp.patch_splitMax(patches)590    self.assertEqual("@@ -1,32 +1,46 @@\n+X\n ab\n+X\n cd\n+X\n ef\n+X\n gh\n+X\n ij\n+X\n kl\n+X\n mn\n+X\n op\n+X\n qr\n+X\n st\n+X\n uv\n+X\n wx\n+X\n yz\n+X\n 012345\n@@ -25,13 +39,18 @@\n zX01\n+X\n 23\n+X\n 45\n+X\n 67\n+X\n 89\n+X\n 0\n", self.dmp.patch_toText(patches))591    patches = self.dmp.patch_make("abcdef1234567890123456789012345678901234567890123456789012345678901234567890uvwxyz", "abcdefuvwxyz")592    oldToText = self.dmp.patch_toText(patches)593    self.dmp.patch_splitMax(patches)594    self.assertEqual(oldToText, self.dmp.patch_toText(patches))595    patches = self.dmp.patch_make("1234567890123456789012345678901234567890123456789012345678901234567890", "abc")596    self.dmp.patch_splitMax(patches)597    self.assertEqual("@@ -1,32 +1,4 @@\n-1234567890123456789012345678\n 9012\n@@ -29,32 +1,4 @@\n-9012345678901234567890123456\n 7890\n@@ -57,14 +1,3 @@\n-78901234567890\n+abc\n", self.dmp.patch_toText(patches))598    patches = self.dmp.patch_make("abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1", "abcdefghij , h : 1 , t : 1 abcdefghij , h : 1 , t : 1 abcdefghij , h : 0 , t : 1")599    self.dmp.patch_splitMax(patches)600    self.assertEqual("@@ -2,32 +2,32 @@\n bcdefghij , h : \n-0\n+1\n  , t : 1 abcdef\n@@ -29,32 +29,32 @@\n bcdefghij , h : \n-0\n+1\n  , t : 1 abcdef\n", self.dmp.patch_toText(patches))601  def testPatchAddPadding(self):602    # Both edges full.603    patches = self.dmp.patch_make("", "test")604    self.assertEqual("@@ -0,0 +1,4 @@\n+test\n", self.dmp.patch_toText(patches))605    self.dmp.patch_addPadding(patches)606    self.assertEqual("@@ -1,8 +1,12 @@\n %01%02%03%04\n+test\n %01%02%03%04\n", self.dmp.patch_toText(patches))607    # Both edges partial.608    patches = self.dmp.patch_make("XY", "XtestY")609    self.assertEqual("@@ -1,2 +1,6 @@\n X\n+test\n Y\n", self.dmp.patch_toText(patches))610    self.dmp.patch_addPadding(patches)611    self.assertEqual("@@ -2,8 +2,12 @@\n %02%03%04X\n+test\n Y%01%02%03\n", self.dmp.patch_toText(patches))612    # Both edges none.613    patches = self.dmp.patch_make("XXXXYYYY", "XXXXtestYYYY")614    self.assertEqual("@@ -1,8 +1,12 @@\n XXXX\n+test\n YYYY\n", self.dmp.patch_toText(patches))615    self.dmp.patch_addPadding(patches)616    self.assertEqual("@@ -5,8 +5,12 @@\n XXXX\n+test\n YYYY\n", self.dmp.patch_toText(patches))617  def testPatchApply(self):618    self.dmp.Match_Distance = 1000619    self.dmp.Match_Threshold = 0.5620    self.dmp.Patch_DeleteThreshold = 0.5621    # Null case.622    patches = self.dmp.patch_make("", "")623    results = self.dmp.patch_apply(patches, "Hello world.")624    self.assertEqual(("Hello world.", []), results)625    # Exact match.626    patches = self.dmp.patch_make("The quick brown fox jumps over the lazy dog.", "That quick brown fox jumped over a lazy dog.")627    results = self.dmp.patch_apply(patches, "The quick brown fox jumps over the lazy dog.")628    self.assertEqual(("That quick brown fox jumped over a lazy dog.", [True, True]), results)629    # Partial match.630    results = self.dmp.patch_apply(patches, "The quick red rabbit jumps over the tired tiger.")631    self.assertEqual(("That quick red rabbit jumped over a tired tiger.", [True, True]), results)632    # Failed match.633    results = self.dmp.patch_apply(patches, "I am the very model of a modern major general.")634    self.assertEqual(("I am the very model of a modern major general.", [False, False]), results)635    # Big delete, small change.636    patches = self.dmp.patch_make("x1234567890123456789012345678901234567890123456789012345678901234567890y", "xabcy")637    results = self.dmp.patch_apply(patches, "x123456789012345678901234567890-----++++++++++-----123456789012345678901234567890y")638    self.assertEqual(("xabcy", [True, True]), results)639    # Big delete, big change 1.640    patches = self.dmp.patch_make("x1234567890123456789012345678901234567890123456789012345678901234567890y", "xabcy")641    results = self.dmp.patch_apply(patches, "x12345678901234567890---------------++++++++++---------------12345678901234567890y")642    self.assertEqual(("xabc12345678901234567890---------------++++++++++---------------12345678901234567890y", [False, True]), results)643    # Big delete, big change 2.644    self.dmp.Patch_DeleteThreshold = 0.6645    patches = self.dmp.patch_make("x1234567890123456789012345678901234567890123456789012345678901234567890y", "xabcy")646    results = self.dmp.patch_apply(patches, "x12345678901234567890---------------++++++++++---------------12345678901234567890y")647    self.assertEqual(("xabcy", [True, True]), results)648    self.dmp.Patch_DeleteThreshold = 0.5649    # Compensate for failed patch.650    self.dmp.Match_Threshold = 0.0651    self.dmp.Match_Distance = 0652    patches = self.dmp.patch_make("abcdefghijklmnopqrstuvwxyz--------------------1234567890", "abcXXXXXXXXXXdefghijklmnopqrstuvwxyz--------------------1234567YYYYYYYYYY890")653    results = self.dmp.patch_apply(patches, "ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567890")654    self.assertEqual(("ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567YYYYYYYYYY890", [False, True]), results)655    self.dmp.Match_Threshold = 0.5656    self.dmp.Match_Distance = 1000657    # No side effects.658    patches = self.dmp.patch_make("", "test")659    patchstr = self.dmp.patch_toText(patches)660    results = self.dmp.patch_apply(patches, "")661    self.assertEqual(patchstr, self.dmp.patch_toText(patches))662    # No side effects with major delete.663    patches = self.dmp.patch_make("The quick brown fox jumps over the lazy dog.", "Woof")664    patchstr = self.dmp.patch_toText(patches)665    self.dmp.patch_apply(patches, "The quick brown fox jumps over the lazy dog.")666    self.assertEqual(patchstr, self.dmp.patch_toText(patches))667    # Edge exact match.668    patches = self.dmp.patch_make("", "test")669    self.dmp.patch_apply(patches, "")670    self.assertEqual(("test", [True]), results)671    # Near edge exact match.672    patches = self.dmp.patch_make("XY", "XtestY")673    results = self.dmp.patch_apply(patches, "XY")674    self.assertEqual(("XtestY", [True]), results)675    # Edge partial match.676    patches = self.dmp.patch_make("y", "y123")677    results = self.dmp.patch_apply(patches, "x")678    self.assertEqual(("x123", [True]), results)679if __name__ == "__main__":...

Full Screen

Full Screen

diff_match_patch_test.js

Source:diff_match_patch_test.js Github

copy

Full Screen

1/**2 * Test Harness for Diff Match and Patch3 *4 * Copyright 2006 Google Inc.5 * http://code.google.com/p/google-diff-match-patch/6 *7 * Licensed under the Apache License, Version 2.0 (the "License");8 * you may not use this file except in compliance with the License.9 * You may obtain a copy of the License at10 *11 *   http://www.apache.org/licenses/LICENSE-2.012 *13 * Unless required by applicable law or agreed to in writing, software14 * distributed under the License is distributed on an "AS IS" BASIS,15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.16 * See the License for the specific language governing permissions and17 * limitations under the License.18 */19// If expected and actual are the equivalent, pass the test.20function assertEquivalent(msg, expected, actual) {21  if (typeof actual == 'undefined') {22    // msg is optional.23    actual = expected;24    expected = msg;25    msg = 'Expected: \'' + expected + '\' Actual: \'' + actual + '\'';26  }27  if (_equivalent(expected, actual)) {28    assertEquals(msg, String.toString(expected), String.toString(actual));29  } else {30    assertEquals(msg, expected, actual);31  }32}33// Are a and b the equivalent? -- Recursive.34function _equivalent(a, b) {35  if (a == b) {36    return true;37  }38  if (typeof a == 'object' && typeof b == 'object' && a !== null && b !== null) {39    if (a.toString() != b.toString()) {40      return false;41    }42    for (var p in a) {43      if (!_equivalent(a[p], b[p])) {44        return false;45      }46    }47    for (var p in b) {48      if (!_equivalent(a[p], b[p])) {49        return false;50      }51    }52    return true;53  }54  return false;55}56function diff_rebuildtexts(diffs) {57  // Construct the two texts which made up the diff originally.58  var text1 = '';59  var text2 = '';60  for (var x = 0; x < diffs.length; x++) {61    if (diffs[x][0] != DIFF_INSERT) {62      text1 += diffs[x][1];63    }64    if (diffs[x][0] != DIFF_DELETE) {65      text2 += diffs[x][1];66    }67  }68  return [text1, text2];69}70var dmp = new diff_match_patch();71// DIFF TEST FUNCTIONS72function testDiffCommonPrefix() {73  // Detect any common prefix.74  // Null case.75  assertEquals(0, dmp.diff_commonPrefix('abc', 'xyz'));76  // Non-null case.77  assertEquals(4, dmp.diff_commonPrefix('1234abcdef', '1234xyz'));78  // Whole case.79  assertEquals(4, dmp.diff_commonPrefix('1234', '1234xyz'));80}81function testDiffCommonSuffix() {82  // Detect any common suffix.83  // Null case.84  assertEquals(0, dmp.diff_commonSuffix('abc', 'xyz'));85  // Non-null case.86  assertEquals(4, dmp.diff_commonSuffix('abcdef1234', 'xyz1234'));87  // Whole case.88  assertEquals(4, dmp.diff_commonSuffix('1234', 'xyz1234'));89}90function testDiffCommonOverlap() {91  // Detect any suffix/prefix overlap.92  // Null case.93  assertEquals(0, dmp.diff_commonOverlap_('', 'abcd'));94  // Whole case.95  assertEquals(3, dmp.diff_commonOverlap_('abc', 'abcd'));96  // No overlap.97  assertEquals(0, dmp.diff_commonOverlap_('123456', 'abcd'));98  // Overlap.99  assertEquals(3, dmp.diff_commonOverlap_('123456xxx', 'xxxabcd'));100  // Unicode.101  // Some overly clever languages (C#) may treat ligatures as equal to their102  // component letters.  E.g. U+FB01 == 'fi'103  assertEquals(0, dmp.diff_commonOverlap_('fi', '\ufb01i'));104}105function testDiffHalfMatch() {106  // Detect a halfmatch.107  dmp.Diff_Timeout = 1;108  // No match.109  assertEquals(null, dmp.diff_halfMatch_('1234567890', 'abcdef'));110  assertEquals(null, dmp.diff_halfMatch_('12345', '23'));111  // Single Match.112  assertEquivalent(['12', '90', 'a', 'z', '345678'], dmp.diff_halfMatch_('1234567890', 'a345678z'));113  assertEquivalent(['a', 'z', '12', '90', '345678'], dmp.diff_halfMatch_('a345678z', '1234567890'));114  assertEquivalent(['abc', 'z', '1234', '0', '56789'], dmp.diff_halfMatch_('abc56789z', '1234567890'));115  assertEquivalent(['a', 'xyz', '1', '7890', '23456'], dmp.diff_halfMatch_('a23456xyz', '1234567890'));116  // Multiple Matches.117  assertEquivalent(['12123', '123121', 'a', 'z', '1234123451234'], dmp.diff_halfMatch_('121231234123451234123121', 'a1234123451234z'));118  assertEquivalent(['', '-=-=-=-=-=', 'x', '', 'x-=-=-=-=-=-=-='], dmp.diff_halfMatch_('x-=-=-=-=-=-=-=-=-=-=-=-=', 'xx-=-=-=-=-=-=-='));119  assertEquivalent(['-=-=-=-=-=', '', '', 'y', '-=-=-=-=-=-=-=y'], dmp.diff_halfMatch_('-=-=-=-=-=-=-=-=-=-=-=-=y', '-=-=-=-=-=-=-=yy'));120  // Non-optimal halfmatch.121  // Optimal diff would be -q+x=H-i+e=lloHe+Hu=llo-Hew+y not -qHillo+x=HelloHe-w+Hulloy122  assertEquivalent(['qHillo', 'w', 'x', 'Hulloy', 'HelloHe'], dmp.diff_halfMatch_('qHilloHelloHew', 'xHelloHeHulloy'));123  // Optimal no halfmatch.124  dmp.Diff_Timeout = 0;125  assertEquals(null, dmp.diff_halfMatch_('qHilloHelloHew', 'xHelloHeHulloy'));126}127function testDiffLinesToChars() {128  function assertLinesToCharsResultEquals(a, b) {129    assertEquals(a.chars1, b.chars1);130    assertEquals(a.chars2, b.chars2);131    assertEquivalent(a.lineArray, b.lineArray);132  }133  // Convert lines down to characters.134  assertLinesToCharsResultEquals({chars1: '\x01\x02\x01', chars2: '\x02\x01\x02', lineArray: ['', 'alpha\n', 'beta\n']}, dmp.diff_linesToChars_('alpha\nbeta\nalpha\n', 'beta\nalpha\nbeta\n'));135  assertLinesToCharsResultEquals({chars1: '', chars2: '\x01\x02\x03\x03', lineArray: ['', 'alpha\r\n', 'beta\r\n', '\r\n']}, dmp.diff_linesToChars_('', 'alpha\r\nbeta\r\n\r\n\r\n'));136  assertLinesToCharsResultEquals({chars1: '\x01', chars2: '\x02', lineArray: ['', 'a', 'b']}, dmp.diff_linesToChars_('a', 'b'));137  // More than 256 to reveal any 8-bit limitations.138  var n = 300;139  var lineList = [];140  var charList = [];141  for (var x = 1; x < n + 1; x++) {142    lineList[x - 1] = x + '\n';143    charList[x - 1] = String.fromCharCode(x);144  }145  assertEquals(n, lineList.length);146  var lines = lineList.join('');147  var chars = charList.join('');148  assertEquals(n, chars.length);149  lineList.unshift('');150  assertLinesToCharsResultEquals({chars1: chars, chars2: '', lineArray: lineList}, dmp.diff_linesToChars_(lines, ''));151}152function testDiffCharsToLines() {153  // Convert chars up to lines.154  var diffs = [[DIFF_EQUAL, '\x01\x02\x01'], [DIFF_INSERT, '\x02\x01\x02']];155  dmp.diff_charsToLines_(diffs, ['', 'alpha\n', 'beta\n']);156  assertEquivalent([[DIFF_EQUAL, 'alpha\nbeta\nalpha\n'], [DIFF_INSERT, 'beta\nalpha\nbeta\n']], diffs);157  // More than 256 to reveal any 8-bit limitations.158  var n = 300;159  var lineList = [];160  var charList = [];161  for (var x = 1; x < n + 1; x++) {162    lineList[x - 1] = x + '\n';163    charList[x - 1] = String.fromCharCode(x);164  }165  assertEquals(n, lineList.length);166  var lines = lineList.join('');167  var chars = charList.join('');168  assertEquals(n, chars.length);169  lineList.unshift('');170  var diffs = [[DIFF_DELETE, chars]];171  dmp.diff_charsToLines_(diffs, lineList);172  assertEquivalent([[DIFF_DELETE, lines]], diffs);173}174function testDiffCleanupMerge() {175  // Cleanup a messy diff.176  // Null case.177  var diffs = [];178  dmp.diff_cleanupMerge(diffs);179  assertEquivalent([], diffs);180  // No change case.181  diffs = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_INSERT, 'c']];182  dmp.diff_cleanupMerge(diffs);183  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_INSERT, 'c']], diffs);184  // Merge equalities.185  diffs = [[DIFF_EQUAL, 'a'], [DIFF_EQUAL, 'b'], [DIFF_EQUAL, 'c']];186  dmp.diff_cleanupMerge(diffs);187  assertEquivalent([[DIFF_EQUAL, 'abc']], diffs);188  // Merge deletions.189  diffs = [[DIFF_DELETE, 'a'], [DIFF_DELETE, 'b'], [DIFF_DELETE, 'c']];190  dmp.diff_cleanupMerge(diffs);191  assertEquivalent([[DIFF_DELETE, 'abc']], diffs);192  // Merge insertions.193  diffs = [[DIFF_INSERT, 'a'], [DIFF_INSERT, 'b'], [DIFF_INSERT, 'c']];194  dmp.diff_cleanupMerge(diffs);195  assertEquivalent([[DIFF_INSERT, 'abc']], diffs);196  // Merge interweave.197  diffs = [[DIFF_DELETE, 'a'], [DIFF_INSERT, 'b'], [DIFF_DELETE, 'c'], [DIFF_INSERT, 'd'], [DIFF_EQUAL, 'e'], [DIFF_EQUAL, 'f']];198  dmp.diff_cleanupMerge(diffs);199  assertEquivalent([[DIFF_DELETE, 'ac'], [DIFF_INSERT, 'bd'], [DIFF_EQUAL, 'ef']], diffs);200  // Prefix and suffix detection.201  diffs = [[DIFF_DELETE, 'a'], [DIFF_INSERT, 'abc'], [DIFF_DELETE, 'dc']];202  dmp.diff_cleanupMerge(diffs);203  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'd'], [DIFF_INSERT, 'b'], [DIFF_EQUAL, 'c']], diffs);204  // Prefix and suffix detection with equalities.205  diffs = [[DIFF_EQUAL, 'x'], [DIFF_DELETE, 'a'], [DIFF_INSERT, 'abc'], [DIFF_DELETE, 'dc'], [DIFF_EQUAL, 'y']];206  dmp.diff_cleanupMerge(diffs);207  assertEquivalent([[DIFF_EQUAL, 'xa'], [DIFF_DELETE, 'd'], [DIFF_INSERT, 'b'], [DIFF_EQUAL, 'cy']], diffs);208  // Slide edit left.209  diffs = [[DIFF_EQUAL, 'a'], [DIFF_INSERT, 'ba'], [DIFF_EQUAL, 'c']];210  dmp.diff_cleanupMerge(diffs);211  assertEquivalent([[DIFF_INSERT, 'ab'], [DIFF_EQUAL, 'ac']], diffs);212  // Slide edit right.213  diffs = [[DIFF_EQUAL, 'c'], [DIFF_INSERT, 'ab'], [DIFF_EQUAL, 'a']];214  dmp.diff_cleanupMerge(diffs);215  assertEquivalent([[DIFF_EQUAL, 'ca'], [DIFF_INSERT, 'ba']], diffs);216  // Slide edit left recursive.217  diffs = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_EQUAL, 'c'], [DIFF_DELETE, 'ac'], [DIFF_EQUAL, 'x']];218  dmp.diff_cleanupMerge(diffs);219  assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_EQUAL, 'acx']], diffs);220  // Slide edit right recursive.221  diffs = [[DIFF_EQUAL, 'x'], [DIFF_DELETE, 'ca'], [DIFF_EQUAL, 'c'], [DIFF_DELETE, 'b'], [DIFF_EQUAL, 'a']];222  dmp.diff_cleanupMerge(diffs);223  assertEquivalent([[DIFF_EQUAL, 'xca'], [DIFF_DELETE, 'cba']], diffs);224}225function testDiffCleanupSemanticLossless() {226  // Slide diffs to match logical boundaries.227  // Null case.228  var diffs = [];229  dmp.diff_cleanupSemanticLossless(diffs);230  assertEquivalent([], diffs);231  // Blank lines.232  diffs = [[DIFF_EQUAL, 'AAA\r\n\r\nBBB'], [DIFF_INSERT, '\r\nDDD\r\n\r\nBBB'], [DIFF_EQUAL, '\r\nEEE']];233  dmp.diff_cleanupSemanticLossless(diffs);234  assertEquivalent([[DIFF_EQUAL, 'AAA\r\n\r\n'], [DIFF_INSERT, 'BBB\r\nDDD\r\n\r\n'], [DIFF_EQUAL, 'BBB\r\nEEE']], diffs);235  // Line boundaries.236  diffs = [[DIFF_EQUAL, 'AAA\r\nBBB'], [DIFF_INSERT, ' DDD\r\nBBB'], [DIFF_EQUAL, ' EEE']];237  dmp.diff_cleanupSemanticLossless(diffs);238  assertEquivalent([[DIFF_EQUAL, 'AAA\r\n'], [DIFF_INSERT, 'BBB DDD\r\n'], [DIFF_EQUAL, 'BBB EEE']], diffs);239  // Word boundaries.240  diffs = [[DIFF_EQUAL, 'The c'], [DIFF_INSERT, 'ow and the c'], [DIFF_EQUAL, 'at.']];241  dmp.diff_cleanupSemanticLossless(diffs);242  assertEquivalent([[DIFF_EQUAL, 'The '], [DIFF_INSERT, 'cow and the '], [DIFF_EQUAL, 'cat.']], diffs);243  // Alphanumeric boundaries.244  diffs = [[DIFF_EQUAL, 'The-c'], [DIFF_INSERT, 'ow-and-the-c'], [DIFF_EQUAL, 'at.']];245  dmp.diff_cleanupSemanticLossless(diffs);246  assertEquivalent([[DIFF_EQUAL, 'The-'], [DIFF_INSERT, 'cow-and-the-'], [DIFF_EQUAL, 'cat.']], diffs);247  // Hitting the start.248  diffs = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'a'], [DIFF_EQUAL, 'ax']];249  dmp.diff_cleanupSemanticLossless(diffs);250  assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_EQUAL, 'aax']], diffs);251  // Hitting the end.252  diffs = [[DIFF_EQUAL, 'xa'], [DIFF_DELETE, 'a'], [DIFF_EQUAL, 'a']];253  dmp.diff_cleanupSemanticLossless(diffs);254  assertEquivalent([[DIFF_EQUAL, 'xaa'], [DIFF_DELETE, 'a']], diffs);255  // Sentence boundaries.256  diffs = [[DIFF_EQUAL, 'The xxx. The '], [DIFF_INSERT, 'zzz. The '], [DIFF_EQUAL, 'yyy.']];257  dmp.diff_cleanupSemanticLossless(diffs);258  assertEquivalent([[DIFF_EQUAL, 'The xxx.'], [DIFF_INSERT, ' The zzz.'], [DIFF_EQUAL, ' The yyy.']], diffs);259}260function testDiffCleanupSemantic() {261  // Cleanup semantically trivial equalities.262  // Null case.263  var diffs = [];264  dmp.diff_cleanupSemantic(diffs);265  assertEquivalent([], diffs);266  // No elimination #1.267  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, 'cd'], [DIFF_EQUAL, '12'], [DIFF_DELETE, 'e']];268  dmp.diff_cleanupSemantic(diffs);269  assertEquivalent([[DIFF_DELETE, 'ab'], [DIFF_INSERT, 'cd'], [DIFF_EQUAL, '12'], [DIFF_DELETE, 'e']], diffs);270  // No elimination #2.271  diffs = [[DIFF_DELETE, 'abc'], [DIFF_INSERT, 'ABC'], [DIFF_EQUAL, '1234'], [DIFF_DELETE, 'wxyz']];272  dmp.diff_cleanupSemantic(diffs);273  assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_INSERT, 'ABC'], [DIFF_EQUAL, '1234'], [DIFF_DELETE, 'wxyz']], diffs);274  // Simple elimination.275  diffs = [[DIFF_DELETE, 'a'], [DIFF_EQUAL, 'b'], [DIFF_DELETE, 'c']];276  dmp.diff_cleanupSemantic(diffs);277  assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_INSERT, 'b']], diffs);278  // Backpass elimination.279  diffs = [[DIFF_DELETE, 'ab'], [DIFF_EQUAL, 'cd'], [DIFF_DELETE, 'e'], [DIFF_EQUAL, 'f'], [DIFF_INSERT, 'g']];280  dmp.diff_cleanupSemantic(diffs);281  assertEquivalent([[DIFF_DELETE, 'abcdef'], [DIFF_INSERT, 'cdfg']], diffs);282  // Multiple eliminations.283  diffs = [[DIFF_INSERT, '1'], [DIFF_EQUAL, 'A'], [DIFF_DELETE, 'B'], [DIFF_INSERT, '2'], [DIFF_EQUAL, '_'], [DIFF_INSERT, '1'], [DIFF_EQUAL, 'A'], [DIFF_DELETE, 'B'], [DIFF_INSERT, '2']];284  dmp.diff_cleanupSemantic(diffs);285  assertEquivalent([[DIFF_DELETE, 'AB_AB'], [DIFF_INSERT, '1A2_1A2']], diffs);286  // Word boundaries.287  diffs = [[DIFF_EQUAL, 'The c'], [DIFF_DELETE, 'ow and the c'], [DIFF_EQUAL, 'at.']];288  dmp.diff_cleanupSemantic(diffs);289  assertEquivalent([[DIFF_EQUAL, 'The '], [DIFF_DELETE, 'cow and the '], [DIFF_EQUAL, 'cat.']], diffs);290  // No overlap elimination.291  diffs = [[DIFF_DELETE, 'abcxx'], [DIFF_INSERT, 'xxdef']];292  dmp.diff_cleanupSemantic(diffs);293  assertEquivalent([[DIFF_DELETE, 'abcxx'], [DIFF_INSERT, 'xxdef']], diffs);294  // Overlap elimination.295  diffs = [[DIFF_DELETE, 'abcxxx'], [DIFF_INSERT, 'xxxdef']];296  dmp.diff_cleanupSemantic(diffs);297  assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_EQUAL, 'xxx'], [DIFF_INSERT, 'def']], diffs);298  // Reverse overlap elimination.299  diffs = [[DIFF_DELETE, 'xxxabc'], [DIFF_INSERT, 'defxxx']];300  dmp.diff_cleanupSemantic(diffs);301  assertEquivalent([[DIFF_INSERT, 'def'], [DIFF_EQUAL, 'xxx'], [DIFF_DELETE, 'abc']], diffs);302  // Two overlap eliminations.303  diffs = [[DIFF_DELETE, 'abcd1212'], [DIFF_INSERT, '1212efghi'], [DIFF_EQUAL, '----'], [DIFF_DELETE, 'A3'], [DIFF_INSERT, '3BC']];304  dmp.diff_cleanupSemantic(diffs);305  assertEquivalent([[DIFF_DELETE, 'abcd'], [DIFF_EQUAL, '1212'], [DIFF_INSERT, 'efghi'], [DIFF_EQUAL, '----'], [DIFF_DELETE, 'A'], [DIFF_EQUAL, '3'], [DIFF_INSERT, 'BC']], diffs);306}307function testDiffCleanupEfficiency() {308  // Cleanup operationally trivial equalities.309  dmp.Diff_EditCost = 4;310  // Null case.311  var diffs = [];312  dmp.diff_cleanupEfficiency(diffs);313  assertEquivalent([], diffs);314  // No elimination.315  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];316  dmp.diff_cleanupEfficiency(diffs);317  assertEquivalent([[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']], diffs);318  // Four-edit elimination.319  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'xyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];320  dmp.diff_cleanupEfficiency(diffs);321  assertEquivalent([[DIFF_DELETE, 'abxyzcd'], [DIFF_INSERT, '12xyz34']], diffs);322  // Three-edit elimination.323  diffs = [[DIFF_INSERT, '12'], [DIFF_EQUAL, 'x'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];324  dmp.diff_cleanupEfficiency(diffs);325  assertEquivalent([[DIFF_DELETE, 'xcd'], [DIFF_INSERT, '12x34']], diffs);326  // Backpass elimination.327  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'xy'], [DIFF_INSERT, '34'], [DIFF_EQUAL, 'z'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '56']];328  dmp.diff_cleanupEfficiency(diffs);329  assertEquivalent([[DIFF_DELETE, 'abxyzcd'], [DIFF_INSERT, '12xy34z56']], diffs);330  // High cost elimination.331  dmp.Diff_EditCost = 5;332  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];333  dmp.diff_cleanupEfficiency(diffs);334  assertEquivalent([[DIFF_DELETE, 'abwxyzcd'], [DIFF_INSERT, '12wxyz34']], diffs);335  dmp.Diff_EditCost = 4;336}337function testDiffPrettyHtml() {338  // Pretty print.339  var diffs = [[DIFF_EQUAL, 'a\n'], [DIFF_DELETE, '<B>b</B>'], [DIFF_INSERT, 'c&d']];340  assertEquals('<span>a&para;<br></span><del style="background:#ffe6e6;">&lt;B&gt;b&lt;/B&gt;</del><ins style="background:#e6ffe6;">c&amp;d</ins>', dmp.diff_prettyHtml(diffs));341}342function testDiffText() {343  // Compute the source and destination texts.344  var diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, ' lazy']];345  assertEquals('jumps over the lazy', dmp.diff_text1(diffs));346  assertEquals('jumped over a lazy', dmp.diff_text2(diffs));347}348function testDiffDelta() {349  // Convert a diff into delta string.350  var diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, ' lazy'], [DIFF_INSERT, 'old dog']];351  var text1 = dmp.diff_text1(diffs);352  assertEquals('jumps over the lazy', text1);353  var delta = dmp.diff_toDelta(diffs);354  assertEquals('=4\t-1\t+ed\t=6\t-3\t+a\t=5\t+old dog', delta);355  // Convert delta string into a diff.356  assertEquivalent(diffs, dmp.diff_fromDelta(text1, delta));357  // Generates error (19 != 20).358  try {359    dmp.diff_fromDelta(text1 + 'x', delta);360    assertEquals(Error, null);361  } catch (e) {362    // Exception expected.363  }364  // Generates error (19 != 18).365  try {366    dmp.diff_fromDelta(text1.substring(1), delta);367    assertEquals(Error, null);368  } catch (e) {369    // Exception expected.370  }371  // Generates error (%c3%xy invalid Unicode).372  try {373    dmp.diff_fromDelta('', '+%c3%xy');374    assertEquals(Error, null);375  } catch (e) {376    // Exception expected.377  }378  // Test deltas with special characters.379  diffs = [[DIFF_EQUAL, '\u0680 \x00 \t %'], [DIFF_DELETE, '\u0681 \x01 \n ^'], [DIFF_INSERT, '\u0682 \x02 \\ |']];380  text1 = dmp.diff_text1(diffs);381  assertEquals('\u0680 \x00 \t %\u0681 \x01 \n ^', text1);382  delta = dmp.diff_toDelta(diffs);383  assertEquals('=7\t-7\t+%DA%82 %02 %5C %7C', delta);384  // Convert delta string into a diff.385  assertEquivalent(diffs, dmp.diff_fromDelta(text1, delta));386  // Verify pool of unchanged characters.387  diffs = [[DIFF_INSERT, 'A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ']];388  var text2 = dmp.diff_text2(diffs);389  assertEquals('A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ', text2);390  delta = dmp.diff_toDelta(diffs);391  assertEquals('+A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ', delta);392  // Convert delta string into a diff.393  assertEquivalent(diffs, dmp.diff_fromDelta('', delta));394}395function testDiffXIndex() {396  // Translate a location in text1 to text2.397  // Translation on equality.398  assertEquals(5, dmp.diff_xIndex([[DIFF_DELETE, 'a'], [DIFF_INSERT, '1234'], [DIFF_EQUAL, 'xyz']], 2));399  // Translation on deletion.400  assertEquals(1, dmp.diff_xIndex([[DIFF_EQUAL, 'a'], [DIFF_DELETE, '1234'], [DIFF_EQUAL, 'xyz']], 3));401}402function testDiffLevenshtein() {403  // Levenshtein with trailing equality.404  assertEquals(4, dmp.diff_levenshtein([[DIFF_DELETE, 'abc'], [DIFF_INSERT, '1234'], [DIFF_EQUAL, 'xyz']]));405  // Levenshtein with leading equality.406  assertEquals(4, dmp.diff_levenshtein([[DIFF_EQUAL, 'xyz'], [DIFF_DELETE, 'abc'], [DIFF_INSERT, '1234']]));407  // Levenshtein with middle equality.408  assertEquals(7, dmp.diff_levenshtein([[DIFF_DELETE, 'abc'], [DIFF_EQUAL, 'xyz'], [DIFF_INSERT, '1234']]));409}410function testDiffBisect() {411  // Normal.412  var a = 'cat';413  var b = 'map';414  // Since the resulting diff hasn't been normalized, it would be ok if415  // the insertion and deletion pairs are swapped.416  // If the order changes, tweak this test as required.417  assertEquivalent([[DIFF_DELETE, 'c'], [DIFF_INSERT, 'm'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, 't'], [DIFF_INSERT, 'p']], dmp.diff_bisect_(a, b, Number.MAX_VALUE));418  // Timeout.419  assertEquivalent([[DIFF_DELETE, 'cat'], [DIFF_INSERT, 'map']], dmp.diff_bisect_(a, b, 0));420}421function testDiffMain() {422  // Perform a trivial diff.423  // Null case.424  assertEquivalent([], dmp.diff_main('', '', false));425  // Equality.426  assertEquivalent([[DIFF_EQUAL, 'abc']], dmp.diff_main('abc', 'abc', false));427  // Simple insertion.428  assertEquivalent([[DIFF_EQUAL, 'ab'], [DIFF_INSERT, '123'], [DIFF_EQUAL, 'c']], dmp.diff_main('abc', 'ab123c', false));429  // Simple deletion.430  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, '123'], [DIFF_EQUAL, 'bc']], dmp.diff_main('a123bc', 'abc', false));431  // Two insertions.432  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_INSERT, '123'], [DIFF_EQUAL, 'b'], [DIFF_INSERT, '456'], [DIFF_EQUAL, 'c']], dmp.diff_main('abc', 'a123b456c', false));433  // Two deletions.434  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, '123'], [DIFF_EQUAL, 'b'], [DIFF_DELETE, '456'], [DIFF_EQUAL, 'c']], dmp.diff_main('a123b456c', 'abc', false));435  // Perform a real diff.436  // Switch off the timeout.437  dmp.Diff_Timeout = 0;438  // Simple cases.439  assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_INSERT, 'b']], dmp.diff_main('a', 'b', false));440  assertEquivalent([[DIFF_DELETE, 'Apple'], [DIFF_INSERT, 'Banana'], [DIFF_EQUAL, 's are a'], [DIFF_INSERT, 'lso'], [DIFF_EQUAL, ' fruit.']], dmp.diff_main('Apples are a fruit.', 'Bananas are also fruit.', false));441  assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_INSERT, '\u0680'], [DIFF_EQUAL, 'x'], [DIFF_DELETE, '\t'], [DIFF_INSERT, '\0']], dmp.diff_main('ax\t', '\u0680x\0', false));442  // Overlaps.443  assertEquivalent([[DIFF_DELETE, '1'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, 'y'], [DIFF_EQUAL, 'b'], [DIFF_DELETE, '2'], [DIFF_INSERT, 'xab']], dmp.diff_main('1ayb2', 'abxab', false));444  assertEquivalent([[DIFF_INSERT, 'xaxcx'], [DIFF_EQUAL, 'abc'], [DIFF_DELETE, 'y']], dmp.diff_main('abcy', 'xaxcxabc', false));445  assertEquivalent([[DIFF_DELETE, 'ABCD'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, '='], [DIFF_INSERT, '-'], [DIFF_EQUAL, 'bcd'], [DIFF_DELETE, '='], [DIFF_INSERT, '-'], [DIFF_EQUAL, 'efghijklmnopqrs'], [DIFF_DELETE, 'EFGHIJKLMNOefg']], dmp.diff_main('ABCDa=bcd=efghijklmnopqrsEFGHIJKLMNOefg', 'a-bcd-efghijklmnopqrs', false));446  // Large equality.447  assertEquivalent([[DIFF_INSERT, ' '], [DIFF_EQUAL, 'a'], [DIFF_INSERT, 'nd'], [DIFF_EQUAL, ' [[Pennsylvania]]'], [DIFF_DELETE, ' and [[New']], dmp.diff_main('a [[Pennsylvania]] and [[New', ' and [[Pennsylvania]]', false));448  // Timeout.449  dmp.Diff_Timeout = 0.1;  // 100ms450  var a = '`Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.\n';451  var b = 'I am the very model of a modern major general,\nI\'ve information vegetable, animal, and mineral,\nI know the kings of England, and I quote the fights historical,\nFrom Marathon to Waterloo, in order categorical.\n';452  // Increase the text lengths by 1024 times to ensure a timeout.453  for (var x = 0; x < 10; x++) {454    a = a + a;455    b = b + b;456  }457  var startTime = (new Date()).getTime();458  dmp.diff_main(a, b);459  var endTime = (new Date()).getTime();460  // Test that we took at least the timeout period.461  assertTrue(dmp.Diff_Timeout * 1000 <= endTime - startTime);462  // Test that we didn't take forever (be forgiving).463  // Theoretically this test could fail very occasionally if the464  // OS task swaps or locks up for a second at the wrong moment.465  // ****466  // TODO(fraser): For unknown reasons this is taking 500 ms on Google's467  // internal test system.  Whereas browsers take 140 ms.468  //assertTrue(dmp.Diff_Timeout * 1000 * 2 > endTime - startTime);469  // ****470  dmp.Diff_Timeout = 0;471  // Test the linemode speedup.472  // Must be long to pass the 100 char cutoff.473  // Simple line-mode.474  a = '1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n';475  b = 'abcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\n';476  assertEquivalent(dmp.diff_main(a, b, false), dmp.diff_main(a, b, true));477  // Single line-mode.478  a = '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890';479  b = 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij';480  assertEquivalent(dmp.diff_main(a, b, false), dmp.diff_main(a, b, true));481  // Overlap line-mode.482  a = '1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n';483  b = 'abcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n';484  var texts_linemode = diff_rebuildtexts(dmp.diff_main(a, b, true));485  var texts_textmode = diff_rebuildtexts(dmp.diff_main(a, b, false));486  assertEquivalent(texts_textmode, texts_linemode);487  // Test null inputs.488  try {489    dmp.diff_main(null, null);490    assertEquals(Error, null);491  } catch (e) {492    // Exception expected.493  }494}495// MATCH TEST FUNCTIONS496function testMatchAlphabet() {497  // Initialise the bitmasks for Bitap.498  // Unique.499  assertEquivalent({'a':4, 'b':2, 'c':1}, dmp.match_alphabet_('abc'));500  // Duplicates.501  assertEquivalent({'a':37, 'b':18, 'c':8}, dmp.match_alphabet_('abcaba'));502}503function testMatchBitap() {504  // Bitap algorithm.505  dmp.Match_Distance = 100;506  dmp.Match_Threshold = 0.5;507  // Exact matches.508  assertEquals(5, dmp.match_bitap_('abcdefghijk', 'fgh', 5));509  assertEquals(5, dmp.match_bitap_('abcdefghijk', 'fgh', 0));510  // Fuzzy matches.511  assertEquals(4, dmp.match_bitap_('abcdefghijk', 'efxhi', 0));512  assertEquals(2, dmp.match_bitap_('abcdefghijk', 'cdefxyhijk', 5));513  assertEquals(-1, dmp.match_bitap_('abcdefghijk', 'bxy', 1));514  // Overflow.515  assertEquals(2, dmp.match_bitap_('123456789xx0', '3456789x0', 2));516  // Threshold test.517  dmp.Match_Threshold = 0.4;518  assertEquals(4, dmp.match_bitap_('abcdefghijk', 'efxyhi', 1));519  dmp.Match_Threshold = 0.3;520  assertEquals(-1, dmp.match_bitap_('abcdefghijk', 'efxyhi', 1));521  dmp.Match_Threshold = 0.0;522  assertEquals(1, dmp.match_bitap_('abcdefghijk', 'bcdef', 1));523  dmp.Match_Threshold = 0.5;524  // Multiple select.525  assertEquals(0, dmp.match_bitap_('abcdexyzabcde', 'abccde', 3));526  assertEquals(8, dmp.match_bitap_('abcdexyzabcde', 'abccde', 5));527  // Distance test.528  dmp.Match_Distance = 10;  // Strict location.529  assertEquals(-1, dmp.match_bitap_('abcdefghijklmnopqrstuvwxyz', 'abcdefg', 24));530  assertEquals(0, dmp.match_bitap_('abcdefghijklmnopqrstuvwxyz', 'abcdxxefg', 1));531  dmp.Match_Distance = 1000;  // Loose location.532  assertEquals(0, dmp.match_bitap_('abcdefghijklmnopqrstuvwxyz', 'abcdefg', 24));533}534function testMatchMain() {535  // Full match.536  // Shortcut matches.537  assertEquals(0, dmp.match_main('abcdef', 'abcdef', 1000));538  assertEquals(-1, dmp.match_main('', 'abcdef', 1));539  assertEquals(3, dmp.match_main('abcdef', '', 3));540  assertEquals(3, dmp.match_main('abcdef', 'de', 3));541  // Beyond end match.542  assertEquals(3, dmp.match_main("abcdef", "defy", 4));543  // Oversized pattern.544  assertEquals(0, dmp.match_main("abcdef", "abcdefy", 0));545  // Complex match.546  assertEquals(4, dmp.match_main('I am the very model of a modern major general.', ' that berry ', 5));547  // Test null inputs.548  try {549    dmp.match_main(null, null, 0);550    assertEquals(Error, null);551  } catch (e) {552    // Exception expected.553  }554}555// PATCH TEST FUNCTIONS556function testPatchObj() {557  // Patch Object.558  var p = new diff_match_patch.patch_obj();559  p.start1 = 20;560  p.start2 = 21;561  p.length1 = 18;562  p.length2 = 17;563  p.diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, '\nlaz']];564  var strp = p.toString();565  assertEquals('@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n %0Alaz\n', strp);566}567function testPatchFromText() {568  assertEquivalent([], dmp.patch_fromText(strp));569  var strp = '@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n %0Alaz\n';570  assertEquals(strp, dmp.patch_fromText(strp)[0].toString());571  assertEquals('@@ -1 +1 @@\n-a\n+b\n', dmp.patch_fromText('@@ -1 +1 @@\n-a\n+b\n')[0].toString());572  assertEquals('@@ -1,3 +0,0 @@\n-abc\n', dmp.patch_fromText('@@ -1,3 +0,0 @@\n-abc\n')[0].toString());573  assertEquals('@@ -0,0 +1,3 @@\n+abc\n', dmp.patch_fromText('@@ -0,0 +1,3 @@\n+abc\n')[0].toString());574  // Generates error.575  try {576    dmp.patch_fromText('Bad\nPatch\n');577    assertEquals(Error, null);578  } catch (e) {579    // Exception expected.580  }581}582function testPatchToText() {583  var strp = '@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n  laz\n';584  var p = dmp.patch_fromText(strp);585  assertEquals(strp, dmp.patch_toText(p));586  strp = '@@ -1,9 +1,9 @@\n-f\n+F\n oo+fooba\n@@ -7,9 +7,9 @@\n obar\n-,\n+.\n  tes\n';587  p = dmp.patch_fromText(strp);588  assertEquals(strp, dmp.patch_toText(p));589}590function testPatchAddContext() {591  dmp.Patch_Margin = 4;592  var p = dmp.patch_fromText('@@ -21,4 +21,10 @@\n-jump\n+somersault\n')[0];593  dmp.patch_addContext_(p, 'The quick brown fox jumps over the lazy dog.');594  assertEquals('@@ -17,12 +17,18 @@\n fox \n-jump\n+somersault\n s ov\n', p.toString());595  // Same, but not enough trailing context.596  p = dmp.patch_fromText('@@ -21,4 +21,10 @@\n-jump\n+somersault\n')[0];597  dmp.patch_addContext_(p, 'The quick brown fox jumps.');598  assertEquals('@@ -17,10 +17,16 @@\n fox \n-jump\n+somersault\n s.\n', p.toString());599  // Same, but not enough leading context.600  p = dmp.patch_fromText('@@ -3 +3,2 @@\n-e\n+at\n')[0];601  dmp.patch_addContext_(p, 'The quick brown fox jumps.');602  assertEquals('@@ -1,7 +1,8 @@\n Th\n-e\n+at\n  qui\n', p.toString());603  // Same, but with ambiguity.604  p = dmp.patch_fromText('@@ -3 +3,2 @@\n-e\n+at\n')[0];605  dmp.patch_addContext_(p, 'The quick brown fox jumps.  The quick brown fox crashes.');606  assertEquals('@@ -1,27 +1,28 @@\n Th\n-e\n+at\n  quick brown fox jumps. \n', p.toString());607}608function testPatchMake() {609  // Null case.610  var patches = dmp.patch_make('', '');611  assertEquals('', dmp.patch_toText(patches));612  var text1 = 'The quick brown fox jumps over the lazy dog.';613  var text2 = 'That quick brown fox jumped over a lazy dog.';614  // Text2+Text1 inputs.615  var expectedPatch = '@@ -1,8 +1,7 @@\n Th\n-at\n+e\n  qui\n@@ -21,17 +21,18 @@\n jump\n-ed\n+s\n  over \n-a\n+the\n  laz\n';616  // The second patch must be "-21,17 +21,18", not "-22,17 +21,18" due to rolling context.617  patches = dmp.patch_make(text2, text1);618  assertEquals(expectedPatch, dmp.patch_toText(patches));619  // Text1+Text2 inputs.620  expectedPatch = '@@ -1,11 +1,12 @@\n Th\n-e\n+at\n  quick b\n@@ -22,18 +22,17 @@\n jump\n-s\n+ed\n  over \n-the\n+a\n  laz\n';621  patches = dmp.patch_make(text1, text2);622  assertEquals(expectedPatch, dmp.patch_toText(patches));623  // Diff input.624  var diffs = dmp.diff_main(text1, text2, false);625  patches = dmp.patch_make(diffs);626  assertEquals(expectedPatch, dmp.patch_toText(patches));627  // Text1+Diff inputs.628  patches = dmp.patch_make(text1, diffs);629  assertEquals(expectedPatch, dmp.patch_toText(patches));630  // Text1+Text2+Diff inputs (deprecated).631  patches = dmp.patch_make(text1, text2, diffs);632  assertEquals(expectedPatch, dmp.patch_toText(patches));633  // Character encoding.634  patches = dmp.patch_make('`1234567890-=[]\\;\',./', '~!@#$%^&*()_+{}|:"<>?');635  assertEquals('@@ -1,21 +1,21 @@\n-%601234567890-=%5B%5D%5C;\',./\n+~!@#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\n', dmp.patch_toText(patches));636  // Character decoding.637  diffs = [[DIFF_DELETE, '`1234567890-=[]\\;\',./'], [DIFF_INSERT, '~!@#$%^&*()_+{}|:"<>?']];638  assertEquivalent(diffs, dmp.patch_fromText('@@ -1,21 +1,21 @@\n-%601234567890-=%5B%5D%5C;\',./\n+~!@#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\n')[0].diffs);639  // Long string with repeats.640  text1 = '';641  for (var x = 0; x < 100; x++) {642    text1 += 'abcdef';643  }644  text2 = text1 + '123';645  expectedPatch = '@@ -573,28 +573,31 @@\n cdefabcdefabcdefabcdefabcdef\n+123\n';646  patches = dmp.patch_make(text1, text2);647  assertEquals(expectedPatch, dmp.patch_toText(patches));648  // Test null inputs.649  try {650    dmp.patch_make(null);651    assertEquals(Error, null);652  } catch (e) {653    // Exception expected.654  }655}656function testPatchSplitMax() {657  // Assumes that dmp.Match_MaxBits is 32.658  var patches = dmp.patch_make('abcdefghijklmnopqrstuvwxyz01234567890', 'XabXcdXefXghXijXklXmnXopXqrXstXuvXwxXyzX01X23X45X67X89X0');659  dmp.patch_splitMax(patches);660  assertEquals('@@ -1,32 +1,46 @@\n+X\n ab\n+X\n cd\n+X\n ef\n+X\n gh\n+X\n ij\n+X\n kl\n+X\n mn\n+X\n op\n+X\n qr\n+X\n st\n+X\n uv\n+X\n wx\n+X\n yz\n+X\n 012345\n@@ -25,13 +39,18 @@\n zX01\n+X\n 23\n+X\n 45\n+X\n 67\n+X\n 89\n+X\n 0\n', dmp.patch_toText(patches));661  patches = dmp.patch_make('abcdef1234567890123456789012345678901234567890123456789012345678901234567890uvwxyz', 'abcdefuvwxyz');662  var oldToText = dmp.patch_toText(patches);663  dmp.patch_splitMax(patches);664  assertEquals(oldToText, dmp.patch_toText(patches));665  patches = dmp.patch_make('1234567890123456789012345678901234567890123456789012345678901234567890', 'abc');666  dmp.patch_splitMax(patches);667  assertEquals('@@ -1,32 +1,4 @@\n-1234567890123456789012345678\n 9012\n@@ -29,32 +1,4 @@\n-9012345678901234567890123456\n 7890\n@@ -57,14 +1,3 @@\n-78901234567890\n+abc\n', dmp.patch_toText(patches));668  patches = dmp.patch_make('abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1', 'abcdefghij , h : 1 , t : 1 abcdefghij , h : 1 , t : 1 abcdefghij , h : 0 , t : 1');669  dmp.patch_splitMax(patches);670  assertEquals('@@ -2,32 +2,32 @@\n bcdefghij , h : \n-0\n+1\n  , t : 1 abcdef\n@@ -29,32 +29,32 @@\n bcdefghij , h : \n-0\n+1\n  , t : 1 abcdef\n', dmp.patch_toText(patches));671}672function testPatchAddPadding() {673  // Both edges full.674  var patches = dmp.patch_make('', 'test');675  assertEquals('@@ -0,0 +1,4 @@\n+test\n', dmp.patch_toText(patches));676  dmp.patch_addPadding(patches);677  assertEquals('@@ -1,8 +1,12 @@\n %01%02%03%04\n+test\n %01%02%03%04\n', dmp.patch_toText(patches));678  // Both edges partial.679  patches = dmp.patch_make('XY', 'XtestY');680  assertEquals('@@ -1,2 +1,6 @@\n X\n+test\n Y\n', dmp.patch_toText(patches));681  dmp.patch_addPadding(patches);682  assertEquals('@@ -2,8 +2,12 @@\n %02%03%04X\n+test\n Y%01%02%03\n', dmp.patch_toText(patches));683  // Both edges none.684  patches = dmp.patch_make('XXXXYYYY', 'XXXXtestYYYY');685  assertEquals('@@ -1,8 +1,12 @@\n XXXX\n+test\n YYYY\n', dmp.patch_toText(patches));686  dmp.patch_addPadding(patches);687  assertEquals('@@ -5,8 +5,12 @@\n XXXX\n+test\n YYYY\n', dmp.patch_toText(patches));688}689function testPatchApply() {690  dmp.Match_Distance = 1000;691  dmp.Match_Threshold = 0.5;692  dmp.Patch_DeleteThreshold = 0.5;693  // Null case.694  var patches = dmp.patch_make('', '');695  var results = dmp.patch_apply(patches, 'Hello world.');696  assertEquivalent(['Hello world.', []], results);697  // Exact match.698  patches = dmp.patch_make('The quick brown fox jumps over the lazy dog.', 'That quick brown fox jumped over a lazy dog.');699  results = dmp.patch_apply(patches, 'The quick brown fox jumps over the lazy dog.');700  assertEquivalent(['That quick brown fox jumped over a lazy dog.', [true, true]], results);701  // Partial match.702  results = dmp.patch_apply(patches, 'The quick red rabbit jumps over the tired tiger.');703  assertEquivalent(['That quick red rabbit jumped over a tired tiger.', [true, true]], results);704  // Failed match.705  results = dmp.patch_apply(patches, 'I am the very model of a modern major general.');706  assertEquivalent(['I am the very model of a modern major general.', [false, false]], results);707  // Big delete, small change.708  patches = dmp.patch_make('x1234567890123456789012345678901234567890123456789012345678901234567890y', 'xabcy');709  results = dmp.patch_apply(patches, 'x123456789012345678901234567890-----++++++++++-----123456789012345678901234567890y');710  assertEquivalent(['xabcy', [true, true]], results);711  // Big delete, big change 1.712  patches = dmp.patch_make('x1234567890123456789012345678901234567890123456789012345678901234567890y', 'xabcy');713  results = dmp.patch_apply(patches, 'x12345678901234567890---------------++++++++++---------------12345678901234567890y');714  assertEquivalent(['xabc12345678901234567890---------------++++++++++---------------12345678901234567890y', [false, true]], results);715  // Big delete, big change 2.716  dmp.Patch_DeleteThreshold = 0.6;717  patches = dmp.patch_make('x1234567890123456789012345678901234567890123456789012345678901234567890y', 'xabcy');718  results = dmp.patch_apply(patches, 'x12345678901234567890---------------++++++++++---------------12345678901234567890y');719  assertEquivalent(['xabcy', [true, true]], results);720  dmp.Patch_DeleteThreshold = 0.5;721  // Compensate for failed patch.722  dmp.Match_Threshold = 0.0;723  dmp.Match_Distance = 0;724  patches = dmp.patch_make('abcdefghijklmnopqrstuvwxyz--------------------1234567890', 'abcXXXXXXXXXXdefghijklmnopqrstuvwxyz--------------------1234567YYYYYYYYYY890');725  results = dmp.patch_apply(patches, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567890');726  assertEquivalent(['ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567YYYYYYYYYY890', [false, true]], results);727  dmp.Match_Threshold = 0.5;728  dmp.Match_Distance = 1000;729  // No side effects.730  patches = dmp.patch_make('', 'test');731  var patchstr = dmp.patch_toText(patches);732  dmp.patch_apply(patches, '');733  assertEquals(patchstr, dmp.patch_toText(patches));734  // No side effects with major delete.735  patches = dmp.patch_make('The quick brown fox jumps over the lazy dog.', 'Woof');736  patchstr = dmp.patch_toText(patches);737  dmp.patch_apply(patches, 'The quick brown fox jumps over the lazy dog.');738  assertEquals(patchstr, dmp.patch_toText(patches));739  // Edge exact match.740  patches = dmp.patch_make('', 'test');741  results = dmp.patch_apply(patches, '');742  assertEquivalent(['test', [true]], results);743  // Near edge exact match.744  patches = dmp.patch_make('XY', 'XtestY');745  results = dmp.patch_apply(patches, 'XY');746  assertEquivalent(['XtestY', [true]], results);747  // Edge partial match.748  patches = dmp.patch_make('y', 'y123');749  results = dmp.patch_apply(patches, 'x');750  assertEquivalent(['x123', [true]], results);...

Full Screen

Full Screen

fastdiff.js

Source:fastdiff.js Github

copy

Full Screen

...8import diffToChanges from '../src/difftochanges';9describe( 'fastDiff', () => {10	describe( 'input types', () => {11		it( 'should correctly handle strings', () => {12			const changes = fastDiff( '123', 'abc123' );13			expect( changes ).to.deep.equal( [ { index: 0, type: 'insert', values: [ 'a', 'b', 'c' ] } ] );14		} );15		it( 'should correctly handle arrays', () => {16			const changes = fastDiff( [ '1', '2', '3' ], [ 'a', 'b', 'c', '1', '2', '3' ] );17			expect( changes ).to.deep.equal( [ { index: 0, type: 'insert', values: [ 'a', 'b', 'c' ] } ] );18		} );19		it( 'should correctly handle node lists', () => {20			const el1 = document.createElement( 'p' );21			const el2 = document.createElement( 'h1' );22			el1.appendChild( document.createElement( 'span' ) );23			el1.appendChild( document.createElement( 'strong' ) );24			el2.appendChild( document.createElement( 'div' ) );25			el2.appendChild( document.createElement( 'strong' ) );26			const changes = fastDiff( el1.childNodes, el2.childNodes );27			expect( changes ).to.deep.equal( [28				{ index: 0, type: 'insert', values: [ el2.childNodes[ 0 ], el2.childNodes[ 1 ] ] },29				{ index: 2, type: 'delete', howMany: 2 }30			] );31		} );32	} );33	describe( 'changes object', () => {34		it( 'should diff identical texts', () => {35			expectDiff( '123', '123', [] );36		} );37		it( 'should diff identical arrays', () => {38			expectDiff( [ '1', '2', '3' ], [ '1', '2', '3' ], [] );39		} );40		it( 'should diff arrays with custom comparator', () => {41			expectDiff( [ 'a', 'b', 'c' ], [ 'A', 'B', 'C' ], [], true, ( a, b ) => a.toLowerCase() === b.toLowerCase() );42		} );43		describe( 'insertion', () => {44			it( 'should diff if old text is empty', () => {45				expectDiff( '', '123', [ { index: 0, type: 'insert', values: [ '1', '2', '3' ] } ] );46			} );47			it( 'should diff if old array is empty', () => {48				expectDiff( [], [ '1', '2', '3' ], [ { index: 0, type: 'insert', values: [ '1', '2', '3' ] } ] );49			} );50			it( 'should diff insertion on the beginning', () => {51				expectDiff( '123', 'abc123', [ { index: 0, type: 'insert', values: [ 'a', 'b', 'c' ] } ] );52			} );53			it( 'should diff insertion on the beginning (repetitive substring)', () => {54				// Do not check compatibility with 'diffToChanges' as it generates:55				// [ { index: 0, type: 'insert', values: [ 'a', 'b' ] }, { index: 5, type: 'insert', values: [ 'c', '1', '2', '3' ] } ]56				expectDiff( '123', 'ab123c123', [ { index: 0, type: 'insert', values: [ 'a', 'b', '1', '2', '3', 'c' ] } ], false );57			} );58			it( 'should diff insertion on the end', () => {59				expectDiff( '123', '123abc', [ { index: 3, type: 'insert', values: [ 'a', 'b', 'c' ] } ] );60			} );61			it( 'should diff insertion on the end (repetitive substring)', () => {62				expectDiff( '123', '123ab123c', [ { index: 3, type: 'insert', values: [ 'a', 'b', '1', '2', '3', 'c' ] } ] );63			} );64			it( 'should diff insertion in the middle', () => {65				expectDiff( '123', '12abc3', [ { index: 2, type: 'insert', values: [ 'a', 'b', 'c' ] } ] );66			} );67			it( 'should diff insertion in the middle (repetitive substring)', () => {68				// Do not check compatibility with 'diffToChanges' as it generates:69				// [ { index: 2, type: 'insert', values: [ 'a', 'b', '1', '2' ] }, { index: 7, type: 'insert', values: [ 'c', '3' ] } ]70				expectDiff( '123', '12ab123c3', [ { index: 2, type: 'insert', values: [ 'a', 'b', '1', '2', '3', 'c' ] } ], false );71			} );72			it( 'should diff insertion of duplicated content', () => {73				expectDiff( '123', '123123', [ { index: 3, type: 'insert', values: [ '1', '2', '3' ] } ] );74			} );75			it( 'should diff insertion of partially duplicated content', () => {76				expectDiff( '123', '12323', [ { index: 3, type: 'insert', values: [ '2', '3' ] } ] );77			} );78			it( 'should diff insertion on both boundaries', () => {79				// Do not check compatibility with 'diffToChanges' as it generates:80				// [ { index: 2, type: 'insert', values: [ 'a', 'b' ] }, { index: 5, type: 'insert', values: [ 'c' ] } ]81				expectDiff( '123', 'ab123c', [82					{ index: 0, type: 'insert', values: [ 'a', 'b', '1', '2', '3', 'c' ] },83					{ index: 6, type: 'delete', howMany: 3 }84				], false );85			} );86			it( 'should diff insertion in array of objects', () => {87				const o1 = { foo: 1 };88				const o2 = { bar: 2 };89				expectDiff( [ o1, o2 ], [ o1, o2, { baz: 3 } ], [90					{ index: 2, type: 'insert', values: [ { baz: 3 } ] }91				] );92			} );93			it( 'should diff insertion in array of objects with comparator', () => {94				expectDiff( [ { text: 'foo' }, { text: 'bar' } ], [ { text: 'foo' }, { text: 'bar' }, { text: 'baz' } ], [95					{ index: 2, type: 'insert', values: [ { text: 'baz' } ] }96				], true, ( a, b ) => a.text === b.text );97			} );98			describe( 'with multi-byte unicode', () => {99				describe( 'simple emoji - single unicode code point', () => {100					// 🙂 = '\ud83d\ude42' = 2 chars101					it( 'should properly handle emoji insertion', () => {102						expectDiff( 'abc', 'ab🙂c', [ { index: 2, type: 'insert', values: '🙂'.split( '' ) } ] );103					} );104					it( 'should properly handle emoji insertion on the end', () => {105						expectDiff( 'abc', 'abc🙂', [ { index: 3, type: 'insert', values: '🙂'.split( '' ) } ] );106					} );107					it( 'should properly handle appending to string containing emoji', () => {108						expectDiff( 'abc🙂', 'abc🙂d', [ { index: 5, type: 'insert', values: [ 'd' ] } ] );109					} );110					it( 'should properly handle insertion to string containing emoji', () => {111						expectDiff( 'ab🙂cd', 'ab🙂cde', [ { index: 6, type: 'insert', values: [ 'e' ] } ] );112					} );113				} );114				describe( 'combined emoji - unicode ZWJ sequence', () => {115					// 👩‍🦰 = '\ud83d\udc69\u200d\ud83e\uddB0' = 5 chars116					it( 'should properly handle emoji with ZWJ insertion', () => {117						expectDiff( 'abc', 'ab👩‍🦰c', [ { index: 2, type: 'insert', values: '👩‍🦰'.split( '' ) } ] );118					} );119					it( 'should properly handle emoji (with ZWJ) insertion on the end', () => {120						expectDiff( 'abc', 'abc👩‍🦰', [ { index: 3, type: 'insert', values: '👩‍🦰'.split( '' ) } ] );121					} );122					it( 'should properly handle appending to string containing emoji (with ZWJ)', () => {123						expectDiff( 'ab👩‍🦰', 'ab👩‍🦰c', [ { index: 7, type: 'insert', values: [ 'c' ] } ] );124					} );125					it( 'should properly handle insertion to string containing emoji (with ZWJ)', () => {126						expectDiff( 'a👩‍🦰b', 'a👩‍🦰bc', [ { index: 7, type: 'insert', values: [ 'c' ] } ] );127					} );128				} );129			} );130		} );131		describe( 'deletion', () => {132			it( 'should diff if new text is empty', () => {133				expectDiff( '123', '', [ { index: 0, type: 'delete', howMany: 3 } ] );134			} );135			it( 'should diff if new array is empty', () => {136				expectDiff( [ '1', '2', '3' ], [], [ { index: 0, type: 'delete', howMany: 3 } ] );137			} );138			it( 'should diff deletion on the beginning', () => {139				expectDiff( 'abc123', '123', [ { index: 0, type: 'delete', howMany: 3 } ] );140			} );141			it( 'should diff deletion on the beginning (repetitive substring)', () => {142				// Do not check compatibility with 'diffToChanges' as it generates:143				// [ { index: 0, type: 'delete', howMany: 2 }, { index: 3, type: 'delete', howMany: 4 } ]144				expectDiff( 'ab123c123', '123', [ { index: 0, type: 'delete', howMany: 6 } ], false );145			} );146			it( 'should diff deletion on the end', () => {147				expectDiff( '123abc', '123', [ { index: 3, type: 'delete', howMany: 3 } ] );148			} );149			it( 'should diff deletion on the end (repetitive substring)', () => {150				expectDiff( '123ab123c', '123', [ { index: 3, type: 'delete', howMany: 6 } ] );151			} );152			it( 'should diff deletion in the middle', () => {153				expectDiff( '12abc3', '123', [ { index: 2, type: 'delete', howMany: 3 } ] );154			} );155			it( 'should diff deletion in the middle (repetitive substring)', () => {156				// Do not check compatibility with 'diffToChanges' as it generates:157				// [ { index: 2, type: 'delete', howMany: 4 }, { index: 3, type: 'delete', howMany: 2 } ]158				expectDiff( '12ab123c3', '123', [ { index: 2, type: 'delete', howMany: 6 } ], false );159			} );160			it( 'should diff deletion on both boundaries', () => {161				// Do not check compatibility with 'diffToChanges' as it generates:162				// [ { index: 0, type: 'delete', howMany: 1 }, { index: 3, type: 'delete', howMany: 2 } ]163				expectDiff( '12abc3', '2ab', [164					{ index: 0, type: 'insert', values: [ '2', 'a', 'b' ] },165					{ index: 3, type: 'delete', howMany: 6 }166				], false );167			} );168			it( 'should diff deletion of duplicated content', () => {169				expectDiff( '123123', '123', [ { index: 3, type: 'delete', howMany: 3 } ] );170			} );171			it( 'should diff deletion of partially duplicated content', () => {172				expectDiff( '12323', '123', [ { index: 3, type: 'delete', howMany: 2 } ] );173			} );174			it( 'should diff deletion of partially duplicated content 2', () => {175				// Do not check compatibility with 'diffToChanges' as it generates:176				// [ { index: 1, type: 'delete', howMany: 2 }, { index: 2, type: 'delete', howMany: 1 } ]177				expectDiff( '11233', '13', [ { index: 1, type: 'delete', howMany: 3 } ], false );178			} );179			it( 'should diff deletion in array of objects', () => {180				const o1 = { foo: 1 };181				const o2 = { bar: 2 };182				expectDiff( [ o1, o2 ], [ o2 ], [183					{ index: 0, type: 'delete', howMany: 1 }184				] );185			} );186			it( 'should diff insertion in array of objects with comparator', () => {187				expectDiff( [ { text: 'foo' }, { text: 'bar' } ], [ { text: 'bar' } ], [188					{ index: 0, type: 'delete', howMany: 1 }189				], true, ( a, b ) => a.text === b.text );190			} );191			describe( 'with multi-byte unicode', () => {192				describe( 'simple emoji - single unicode code point', () => {193					// 🙂 = '\ud83d\ude42' = 2 chars194					const emojiLength = '🙂'.split( '' ).length;195					it( 'should properly handle emoji delete', () => {196						expectDiff( 'ab🙂c', 'abc', [ { index: 2, type: 'delete', howMany: emojiLength } ] );197					} );198					it( 'should properly handle emoji delete at end', () => {199						expectDiff( 'ab🙂', 'ab', [ { index: 2, type: 'delete', howMany: emojiLength } ] );200					} );201					it( 'should properly handle emoji delete at beginning', () => {202						expectDiff( '🙂ab', 'ab', [ { index: 0, type: 'delete', howMany: emojiLength } ] );203					} );204				} );205				describe( 'combined emoji - unicode ZWJ sequence', () => {206					// 👩‍🦰 = '\ud83d\udc69\u200d\ud83e\uddB0' = 5 chars207					const emojiLength = '👩‍🦰'.split( '' ).length;208					it( 'should properly handle emoji delete (with ZWJ)', () => {209						expectDiff( 'ab👩‍🦰c', 'abc', [ { index: 2, type: 'delete', howMany: emojiLength } ] );210					} );211					it( 'should properly handle emoji delete at end (with ZWJ)', () => {212						expectDiff( 'ab👩‍🦰', 'ab', [ { index: 2, type: 'delete', howMany: emojiLength } ] );213					} );214					it( 'should properly handle emoji delete at beginning (with ZWJ)', () => {215						expectDiff( '👩‍🦰ab', 'ab', [ { index: 0, type: 'delete', howMany: emojiLength } ] );216					} );217				} );218			} );219		} );220		describe( 'replacement', () => {221			it( 'should diff replacement of entire text', () => {222				// Do not check compatibility with 'diffToChanges' as it has changes in reveres order ('delete', 'insert') here.223				expectDiff( '12345', 'abcd', [224					{ index: 0, type: 'insert', values: [ 'a', 'b', 'c', 'd' ] },225					{ index: 4, type: 'delete', howMany: 5 }226				], false );227			} );228			it( 'should diff replacement on the beginning', () => {229				expectDiff( '12345', 'abcd345', [230					{ index: 0, type: 'insert', values: [ 'a', 'b', 'c', 'd' ] },231					{ index: 4, type: 'delete', howMany: 2 }232				] );233			} );234			it( 'should diff replacement on the beginning (repetitive substring)', () => {235				// Do not check compatibility with 'diffToChanges' as it has changes in reveres order ('delete', 'insert') here.236				expectDiff( '12345', '345345', [237					{ index: 0, type: 'insert', values: [ '3', '4', '5' ] },238					{ index: 3, type: 'delete', howMany: 2 }239				], false );240			} );241			it( 'should diff replacement on the end', () => {242				// Do not check compatibility with 'diffToChanges' as it has changes in reveres order ('delete', 'insert') here.243				expectDiff( '12345', '12ab', [244					{ index: 2, type: 'insert', values: [ 'a', 'b' ] },245					{ index: 4, type: 'delete', howMany: 3 }246				], false );247			} );248			it( 'should diff replacement on the end (repetitive substring)', () => {249				// Do not check compatibility with 'diffToChanges' as it generates:250				// [ { index: 3, type: 'insert', values: [ '1', '2', '3' ] }, { index: 7, type: 'delete', howMany: 1 } ]251				expectDiff( '12345', '1231234', [252					{ index: 3, type: 'insert', values: [ '1', '2', '3', '4' ] },253					{ index: 7, type: 'delete', howMany: 2 }254				], false );255			} );256			it( 'should diff insertion of duplicated content (case 1)', () => {257				expectDiff( '1234', '123123', [258					{ index: 3, type: 'insert', values: [ '1', '2', '3' ] },259					{ index: 6, type: 'delete', howMany: 1 }260				], false );261			} );262			it( 'should diff insertion of duplicated content (case 2)', () => {263				expectDiff( '1234', '13424', [264					{ index: 1, type: 'insert', values: [ '3', '4', '2' ] },265					{ index: 4, type: 'delete', howMany: 2 }266				], false );267			} );268			it( 'should diff replacement in the middle', () => {269				expectDiff( '12345', '12ab5', [270					{ index: 2, type: 'insert', values: [ 'a', 'b' ] },271					{ index: 4, type: 'delete', howMany: 2 }272				] );273			} );274			it( 'should diff replacement in the middle (repetitive substring)', () => {275				// Do not check compatibility with 'diffToChanges' as it generates:276				// [ { index: 2, type: 'insert', values: [ '1', '2' ] }, { index: 7, type: 'insert', values: [ '5' ] } ]277				expectDiff( '12345', '12123455', [278					{ index: 2, type: 'insert', values: [ '1', '2', '3', '4', '5' ] },279					{ index: 7, type: 'delete', howMany: 2 }280				], false );281			} );282			it( 'should diff replacement of duplicated content', () => {283				// Do not check compatibility with 'diffToChanges' as it has changes in reveres order ('delete', 'insert') here.284				expectDiff( '123123', '123333', [285					{ index: 3, type: 'insert', values: '33'.split( '' ) },286					{ index: 5, type: 'delete', howMany: 2 }287				], false );288			} );289			it( 'should diff replacement in array of objects', () => {290				const o1 = { foo: 1 };291				const o2 = { bar: 2 };292				expectDiff( [ o1, o2 ], [ o1, { baz: 3 } ], [293					{ index: 1, type: 'insert', values: [ { baz: 3 } ] },294					{ index: 2, type: 'delete', howMany: 1 }295				] );296			} );297			it( 'should diff insertion in array of objects with comparator', () => {298				expectDiff( [ { text: 'foo' }, { text: 'bar' } ], [ { text: 'foo' }, { text: 'baz' } ], [299					{ index: 1, type: 'insert', values: [ { text: 'baz' } ] },300					{ index: 2, type: 'delete', howMany: 1 }301				], true, ( a, b ) => a.text === b.text );302			} );303			describe( 'with multi-byte unicode', () => {304				// 🙂 = '\ud83d\ude42' = 2 chars305				const smileEmoji = '🙂'.split( '' );306				// 👩 = '\ud83d\udc69' = 2 chars307				const womanEmoji = '👩'.split( '' );308				// 👩‍🦰 = '\ud83d\udc69\u200d\ud83e\uddB0' = 5 chars309				const womanRedHairEmoji = '👩‍🦰'.split( '' );310				// Do not check compatibility with 'diffToChanges' as it generates:311				// [ { index: 1, type: 'delete', howMany: 2 }, { index: 1, type: 'insert', values: [ 'x' ] } ]312				it( 'should properly replace emoji with text', () => {313					expectDiff( 'a🙂b', 'axb', [314						{ index: 1, type: 'insert', values: [ 'x' ] },315						{ index: 2, type: 'delete', howMany: smileEmoji.length }316					], false );317				} );318				it( 'should properly replace text with emoji', () => {319					expectDiff( 'abc', 'a👩c', [320						{ index: 1, type: 'insert', values: womanEmoji },321						{ index: 3, type: 'delete', howMany: 1 }322					] );323				} );324				it( 'should properly replace emoji with emoji', () => {325					// Note that first char of both emoji is the same.326					expectDiff( 'a👩b', 'a🙂b', [327						{ index: 2, type: 'insert', values: smileEmoji.slice( 1 ) },328						{ index: 3, type: 'delete', howMany: 1 }329					] );330				} );331				it( 'should properly replace simple emoji with ZWJ sequence of it', () => {332					// Note that first 2 chars of both emoji are the same.333					expectDiff( 'a👩b', 'a👩‍🦰b', [334						{ index: 3, type: 'insert', values: womanRedHairEmoji.slice( 2 ) }335					] );336				} );337				it( 'should properly replace ZWJ sequence with simple emoji (part of sequence)', () => {338					// Note that first 2 chars of both emoji are the same.339					expectDiff( 'a👩‍🦰b', 'a👩b', [340						{ index: 3, type: 'delete', howMany: 3 }341					] );342				} );343				it( 'should properly replace simple emoji with other ZWJ sequence', () => {344					// Note that first char of both emoji is the same.345					expectDiff( 'a🙂b', 'a👩‍🦰b', [346						{ index: 2, type: 'insert', values: womanRedHairEmoji.slice( 1 ) },347						{ index: 6, type: 'delete', howMany: 1 }348					] );349				} );350			} );351		} );352	} );353	describe( 'changes linear', () => {354		it( 'should diff identical texts', () => {355			expectDiffLinear( '123', '123', 'eee' );356		} );357		it( 'should diff identical arrays', () => {358			expectDiffLinear( [ '1', '2', '3' ], [ '1', '2', '3' ], 'eee' );359		} );360		it( 'should diff arrays with custom comparator', () => {361			expectDiffLinear( [ 'a', 'b', 'c' ], [ 'A', 'B', 'C' ], 'eee', true, ( a, b ) => a.toLowerCase() === b.toLowerCase() );362		} );363		describe( 'insertion', () => {364			it( 'should diff if old text is empty', () => {365				expectDiffLinear( '', '123', 'iii' );366			} );367			it( 'should diff if old array is empty', () => {368				expectDiffLinear( [], [ '1', '2', '3' ], 'iii' );369			} );370			it( 'should diff insertion on the beginning', () => {371				expectDiffLinear( '123', 'abc123', 'iiieee' );372			} );373			it( 'should diff insertion on the beginning (repetitive substring)', () => {374				expectDiffLinear( '123', 'ab123c123', 'iiiiiieee', false );375			} );376			it( 'should diff insertion on the end', () => {377				expectDiffLinear( '123', '123abc', 'eeeiii' );378			} );379			it( 'should diff insertion on the end (repetitive substring)', () => {380				expectDiffLinear( '123', '123ab123c', 'eeeiiiiii' );381			} );382			it( 'should diff insertion in the middle', () => {383				expectDiffLinear( '123', '12abc3', 'eeiiie' );384			} );385			it( 'should diff insertion in the middle (repetitive substring)', () => {386				expectDiffLinear( '123', '12ab123c3', 'eeiiiiiie', false );387			} );388			it( 'should diff insertion of duplicated content', () => {389				expectDiffLinear( '123', '123123', 'eeeiii' );390			} );391			it( 'should diff insertion of partially duplicated content', () => {392				expectDiffLinear( '123', '12323', 'eeeii' );393			} );394			it( 'should diff insertion on both boundaries', () => {395				expectDiffLinear( '123', 'ab123c', 'iiiiiiddd', false );396			} );397			it( 'should diff insertion in array of objects', () => {398				const o1 = { foo: 1 };399				const o2 = { bar: 2 };400				expectDiffLinear( [ o1, o2 ], [ o1, o2, { baz: 3 } ], 'eei' );401			} );402			it( 'should diff insertion in array of objects with comparator', () => {403				expectDiffLinear( [ { text: 'foo' }, { text: 'bar' } ], [ { text: 'foo' }, { text: 'bar' }, { text: 'baz' } ],404					'eei', true, ( a, b ) => a.text === b.text );405			} );406		} );407		describe( 'deletion', () => {408			it( 'should diff if new text is empty', () => {409				expectDiffLinear( '123', '', 'ddd' );410			} );411			it( 'should diff if new array is empty', () => {412				expectDiffLinear( [ '1', '2', '3' ], [], 'ddd' );413			} );414			it( 'should diff deletion on the beginning', () => {415				expectDiffLinear( 'abc123', '123', 'dddeee' );416			} );417			it( 'should diff deletion on the beginning (repetitive substring)', () => {418				expectDiffLinear( 'ab123c123', '123', 'ddddddeee', false );419			} );420			it( 'should diff deletion on the end', () => {421				expectDiffLinear( '123abc', '123', 'eeeddd' );422			} );423			it( 'should diff deletion on the end (repetitive substring)', () => {424				expectDiffLinear( '123ab123c', '123', 'eeedddddd' );425			} );426			it( 'should diff deletion in the middle', () => {427				expectDiffLinear( '12abc3', '123', 'eeddde' );428			} );429			it( 'should diff deletion in the middle (repetitive substring)', () => {430				expectDiffLinear( '12ab123c3', '123', 'eedddddde', false );431			} );432			it( 'should diff deletion on both boundaries', () => {433				expectDiffLinear( '12abc3', '2ab', 'iiidddddd', false );434			} );435			it( 'should diff deletion of duplicated content', () => {436				expectDiffLinear( '123123', '123', 'eeeddd' );437			} );438			it( 'should diff deletion of partially duplicated content', () => {439				expectDiffLinear( '12323', '123', 'eeedd' );440			} );441			it( 'should diff deletion of partially duplicated content 2', () => {442				expectDiffLinear( '11233', '13', 'eddde', false );443			} );444			it( 'should diff deletion in array of objects', () => {445				const o1 = { foo: 1 };446				const o2 = { bar: 2 };447				expectDiffLinear( [ o1, o2 ], [ o2 ], 'de' );448			} );449			it( 'should diff insertion in array of objects with comparator', () => {450				expectDiffLinear( [ { text: 'foo' }, { text: 'bar' } ], [ { text: 'bar' } ], 'de', true, ( a, b ) => a.text === b.text );451			} );452		} );453		describe( 'replacement', () => {454			it( 'should diff replacement of entire text', () => {455				expectDiffLinear( '12345', 'abcd', 'iiiiddddd', false );456			} );457			it( 'should diff replacement on the beginning', () => {458				expectDiffLinear( '12345', 'abcd345', 'iiiiddeee' );459			} );460			it( 'should diff replacement on the beginning (repetitive substring)', () => {461				expectDiffLinear( '12345', '345345', 'iiiddeee', false );462			} );463			it( 'should diff replacement on the end', () => {464				expectDiffLinear( '12345', '12ab', 'eeiiddd', false );465			} );466			it( 'should diff replacement on the end (repetitive substring)', () => {467				expectDiffLinear( '12345', '1231234', 'eeeiiiidd', false );468			} );469			it( 'should diff insertion of duplicated content - case 1', () => {470				expectDiffLinear( '1234', '123123', 'eeeiiid' );471			} );472			it( 'should diff insertion of duplicated content - case 2', () => {473				expectDiffLinear( '1234', '13424', 'eiiidde', false );474			} );475			it( 'should diff replacement in the middle', () => {476				expectDiffLinear( '12345', '12ab5', 'eeiidde' );477			} );478			it( 'should diff replacement in the middle (repetitive substring)', () => {479				expectDiffLinear( '12345', '12123455', 'eeiiiiidde', false );480			} );481			it( 'should diff replacement of duplicated content', () => {482				expectDiffLinear( '123123', '123333', 'eeeiidde', false );483			} );484			it( 'should diff replacement in array of objects', () => {485				const o1 = { foo: 1 };486				const o2 = { bar: 2 };487				expectDiffLinear( [ o1, o2 ], [ o1, { baz: 3 } ], 'eid' );488			} );489			it( 'should diff insertion in array of objects with comparator', () => {490				expectDiffLinear( [ { text: 'foo' }, { text: 'bar' } ], [ { text: 'foo' }, { text: 'baz' } ], 'eid',491					true, ( a, b ) => a.text === b.text );492			} );493		} );494	} );495} );496function expectDiff( oldText, newText, expected, checkDiffToChangesCompatibility = true, comparator = null ) {497	const result = fastDiff( oldText, newText, comparator );498	expect( result ).to.deep.equal( expected, 'fastDiff changes failed' );499	if ( checkDiffToChangesCompatibility ) {500		expect( result ).to.deep.equal(501			diffToChanges( diff( oldText, newText, comparator ), newText ), 'diffToChanges compatibility failed' );502	}503}504function expectDiffLinear( oldText, newText, expected, checkDiffCompatibility = true, comparator = null ) {505	const actions = { d: 'delete', e: 'equal', i: 'insert' };506	const expectedArray = expected.split( '' ).map( item => actions[ item ] );507	const result = fastDiff( oldText, newText, comparator, true );508	expect( result ).to.deep.equal( expectedArray, 'fastDiff linear result failed' );509	if ( checkDiffCompatibility ) {510		expect( result ).to.deep.equal( diff( oldText, newText, comparator ), 'diff compatibility failed' );511	}...

Full Screen

Full Screen

diff.js

Source:diff.js Github

copy

Full Screen

1var moment = require("../../moment");2function equal(test, a, b, message) {3    test.ok(Math.abs(a - b) < 0.00000001, "(" + a + " === " + b + ") " + message);4}5function dstForYear(year) {6    var start = moment([year]),7        end = moment([year + 1]),8        current = start.clone(),9        last;10    while (current < end) {11        last = current.clone();12        current.add(24, 'hour');13        if (last.zone() !== current.zone()) {14            end = current.clone();15            current = last.clone();16            break;17        }18    }19    while (current < end) {20        last = current.clone();21        current.add(1, 'hour');22        if (last.zone() !== current.zone()) {23            return {24                moment : last,25                diff : (current.zone() - last.zone()) / 6026            };27        }28    }29}30exports.diff = {31    "diff" : function (test) {32        test.expect(5);33        test.equal(moment(1000).diff(0), 1000, "1 second - 0 = 1000");34        test.equal(moment(1000).diff(500), 500, "1 second - 0.5 seconds = 500");35        test.equal(moment(0).diff(1000), -1000, "0 - 1 second = -1000");36        test.equal(moment(new Date(1000)).diff(1000), 0, "1 second - 1 second = 0");37        var oneHourDate = new Date(),38            nowDate = new Date(+oneHourDate);39        oneHourDate.setHours(oneHourDate.getHours() + 1);40        test.equal(moment(oneHourDate).diff(nowDate), 60 * 60 * 1000, "1 hour from now = 3600000");41        test.done();42    },43    "diff key after" : function (test) {44        test.expect(10);45        test.equal(moment([2010]).diff([2011], 'years'), -1, "year diff");46        test.equal(moment([2010]).diff([2010, 2], 'months'), -2, "month diff");47        test.equal(moment([2010]).diff([2010, 0, 7], 'weeks'), 0, "week diff");48        test.equal(moment([2010]).diff([2010, 0, 8], 'weeks'), -1, "week diff");49        test.equal(moment([2010]).diff([2010, 0, 21], 'weeks'), -2, "week diff");50        test.equal(moment([2010]).diff([2010, 0, 22], 'weeks'), -3, "week diff");51        test.equal(moment([2010]).diff([2010, 0, 4], 'days'), -3, "day diff");52        test.equal(moment([2010]).diff([2010, 0, 1, 4], 'hours'), -4, "hour diff");53        test.equal(moment([2010]).diff([2010, 0, 1, 0, 5], 'minutes'), -5, "minute diff");54        test.equal(moment([2010]).diff([2010, 0, 1, 0, 0, 6], 'seconds'), -6, "second diff");55        test.done();56    },57    "diff key before" : function (test) {58        test.expect(10);59        test.equal(moment([2011]).diff([2010], 'years'), 1, "year diff");60        test.equal(moment([2010, 2]).diff([2010], 'months'), 2, "month diff");61        test.equal(moment([2010, 0, 4]).diff([2010], 'days'), 3, "day diff");62        test.equal(moment([2010, 0, 7]).diff([2010], 'weeks'), 0, "week diff");63        test.equal(moment([2010, 0, 8]).diff([2010], 'weeks'), 1, "week diff");64        test.equal(moment([2010, 0, 21]).diff([2010], 'weeks'), 2, "week diff");65        test.equal(moment([2010, 0, 22]).diff([2010], 'weeks'), 3, "week diff");66        test.equal(moment([2010, 0, 1, 4]).diff([2010], 'hours'), 4, "hour diff");67        test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'minutes'), 5, "minute diff");68        test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 'seconds'), 6, "second diff");69        test.done();70    },71    "diff key before singular" : function (test) {72        test.expect(10);73        test.equal(moment([2011]).diff([2010], 'year'), 1, "year diff singular");74        test.equal(moment([2010, 2]).diff([2010], 'month'), 2, "month diff singular");75        test.equal(moment([2010, 0, 4]).diff([2010], 'day'), 3, "day diff singular");76        test.equal(moment([2010, 0, 7]).diff([2010], 'week'), 0, "week diff singular");77        test.equal(moment([2010, 0, 8]).diff([2010], 'week'), 1, "week diff singular");78        test.equal(moment([2010, 0, 21]).diff([2010], 'week'), 2, "week diff singular");79        test.equal(moment([2010, 0, 22]).diff([2010], 'week'), 3, "week diff singular");80        test.equal(moment([2010, 0, 1, 4]).diff([2010], 'hour'), 4, "hour diff singular");81        test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'minute'), 5, "minute diff singular");82        test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 'second'), 6, "second diff singular");83        test.done();84    },85    "diff key before abbreviated" : function (test) {86        test.expect(10);87        test.equal(moment([2011]).diff([2010], 'y'), 1, "year diff abbreviated");88        test.equal(moment([2010, 2]).diff([2010], 'M'), 2, "month diff abbreviated");89        test.equal(moment([2010, 0, 4]).diff([2010], 'd'), 3, "day diff abbreviated");90        test.equal(moment([2010, 0, 7]).diff([2010], 'w'), 0, "week diff abbreviated");91        test.equal(moment([2010, 0, 8]).diff([2010], 'w'), 1, "week diff abbreviated");92        test.equal(moment([2010, 0, 21]).diff([2010], 'w'), 2, "week diff abbreviated");93        test.equal(moment([2010, 0, 22]).diff([2010], 'w'), 3, "week diff abbreviated");94        test.equal(moment([2010, 0, 1, 4]).diff([2010], 'h'), 4, "hour diff abbreviated");95        test.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'm'), 5, "minute diff abbreviated");96        test.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 's'), 6, "second diff abbreviated");97        test.done();98    },99    "diff month" : function (test) {100        test.expect(1);101        test.equal(moment([2011, 0, 31]).diff([2011, 2, 1], 'months'), -1, "month diff");102        test.done();103    },104    "diff across DST" : function (test) {105        var dst = dstForYear(2012), a, b, daysInMonth;106        if (!dst) {107            console.log("No DST?");108            test.done();109            return;110        }111        test.expect(16);112        a = dst.moment;113        b = a.clone().utc().add(12, 'hours').local();114        daysInMonth = (a.daysInMonth() + b.daysInMonth()) / 2;115        equal(test, b.diff(a, 'ms', true), 12 * 60 * 60 * 1000,                         "ms diff across DST");116        equal(test, b.diff(a, 's', true),  12 * 60 * 60,                                "second diff across DST");117        equal(test, b.diff(a, 'm', true),  12 * 60,                                     "minute diff across DST");118        equal(test, b.diff(a, 'h', true),  12,                                          "hour diff across DST");119        equal(test, b.diff(a, 'd', true),  (12 - dst.diff) / 24,                        "day diff across DST");120        equal(test, b.diff(a, 'w', true),  (12 - dst.diff) / 24 / 7,                    "week diff across DST");121        equal(test, b.diff(a, 'M', true),  (12 - dst.diff) / 24 / daysInMonth,          "month diff across DST");122        equal(test, b.diff(a, 'y', true),  (12 - dst.diff) / 24 / daysInMonth / 12,     "year diff across DST");123        a = dst.moment;124        b = a.clone().utc().add(12 + dst.diff, 'hours').local();125        daysInMonth = (a.daysInMonth() + b.daysInMonth()) / 2;126        equal(test, b.diff(a, 'ms', true), (12 + dst.diff) * 60 * 60 * 1000,   "ms diff across DST");127        equal(test, b.diff(a, 's', true),  (12 + dst.diff) * 60 * 60,          "second diff across DST");128        equal(test, b.diff(a, 'm', true),  (12 + dst.diff) * 60,               "minute diff across DST");129        equal(test, b.diff(a, 'h', true),  (12 + dst.diff),                    "hour diff across DST");130        equal(test, b.diff(a, 'd', true),  12 / 24,                            "day diff across DST");131        equal(test, b.diff(a, 'w', true),  12 / 24 / 7,                        "week diff across DST");132        equal(test, b.diff(a, 'M', true),  12 / 24 / daysInMonth,              "month diff across DST");133        equal(test, b.diff(a, 'y', true),  12 / 24 / daysInMonth / 12,         "year diff across DST");134        test.done();135    },136    "diff overflow" : function (test) {137        test.expect(4);138        test.equal(moment([2011]).diff([2010], 'months'), 12, "month diff");139        test.equal(moment([2010, 0, 2]).diff([2010], 'hours'), 24, "hour diff");140        test.equal(moment([2010, 0, 1, 2]).diff([2010], 'minutes'), 120, "minute diff");141        test.equal(moment([2010, 0, 1, 0, 4]).diff([2010], 'seconds'), 240, "second diff");142        test.done();143    },144    "diff between utc and local" : function (test) {145        test.expect(7);146        test.equal(moment([2012]).utc().diff([2011], 'years'), 1, "year diff");147        test.equal(moment([2010, 2, 2]).utc().diff([2010, 0, 2], 'months'), 2, "month diff");148        test.equal(moment([2010, 0, 4]).utc().diff([2010], 'days'), 3, "day diff");149        test.equal(moment([2010, 0, 22]).utc().diff([2010], 'weeks'), 3, "week diff");150        test.equal(moment([2010, 0, 1, 4]).utc().diff([2010], 'hours'), 4, "hour diff");151        test.equal(moment([2010, 0, 1, 0, 5]).utc().diff([2010], 'minutes'), 5, "minute diff");152        test.equal(moment([2010, 0, 1, 0, 0, 6]).utc().diff([2010], 'seconds'), 6, "second diff");153        test.done();154    },155    "diff floored" : function (test) {156        test.expect(7);157        test.equal(moment([2010, 0, 1, 23]).diff([2010], 'day'), 0, "23 hours = 0 days");158        test.equal(moment([2010, 0, 1, 23, 59]).diff([2010], 'day'), 0, "23:59 hours = 0 days");159        test.equal(moment([2010, 0, 1, 24]).diff([2010], 'day'), 1, "24 hours = 1 day");160        test.equal(moment([2010, 0, 2]).diff([2011, 0, 1], 'year'), 0, "year rounded down");161        test.equal(moment([2011, 0, 1]).diff([2010, 0, 2], 'year'), 0, "year rounded down");162        test.equal(moment([2010, 0, 2]).diff([2011, 0, 2], 'year'), -1, "year rounded down");163        test.equal(moment([2011, 0, 2]).diff([2010, 0, 2], 'year'), 1, "year rounded down");164        test.done();165    },166    "year diffs include dates" : function (test) {167        test.expect(1);168        test.ok(moment([2012, 1, 19]).diff(moment([2002, 1, 20]), 'years', true) < 10, "year diff should include date of month");169        test.done();170    },171    "month diffs" : function (test) {172        test.expect(8);173        // due to floating point math errors, these tests just need to be accurate within 0.00000001174        equal(test, moment([2012, 0, 1]).diff([2012, 1, 1], 'months', true), -1, 'Jan 1 to Feb 1 should be 1 month');175        equal(test, moment([2012, 0, 1]).diff([2012, 0, 1, 12], 'months', true), -0.5 / 31, 'Jan 1 to Jan 1 noon should be 0.5 / 31 months');176        equal(test, moment([2012, 0, 15]).diff([2012, 1, 15], 'months', true), -1, 'Jan 15 to Feb 15 should be 1 month');177        equal(test, moment([2012, 0, 28]).diff([2012, 1, 28], 'months', true), -1, 'Jan 28 to Feb 28 should be 1 month');178        equal(test, moment([2012, 0, 31]).diff([2012, 1, 29], 'months', true), -1 + (2 / 30), 'Jan 31 to Feb 29 should be 1 - (2 / 30) months');179        equal(test, moment([2012, 0, 31]).diff([2012, 2, 1], 'months', true), -2 + (30 / 31), 'Jan 31 to Mar 1 should be 2 - (30 / 31) months');180        equal(test, moment([2012, 0, 31]).diff([2012, 2, 1, 12], 'months', true), -2 + (29.5 / 31), 'Jan 31 to Mar 1 should be 2 - (29.5 / 31) months');181        equal(test, moment([2012, 0, 1]).diff([2012, 0, 31], 'months', true), -(30 / 31), 'Jan 1 to Jan 31 should be 30 / 31 months');182        test.done();183    },184    "year diffs" : function (test) {185        test.expect(10);186        // due to floating point math errors, these tests just need to be accurate within 0.00000001187        equal(test, moment([2012, 0, 1]).diff([2013, 0, 1], 'years', true), -1, 'Jan 1 2012 to Jan 1 2013 should be 1 year');188        equal(test, moment([2012, 1, 28]).diff([2013, 1, 28], 'years', true), -1, 'Feb 28 2012 to Feb 28 2013 should be 1 year');189        equal(test, moment([2012, 2, 1]).diff([2013, 2, 1], 'years', true), -1, 'Mar 1 2012 to Mar 1 2013 should be 1 year');190        equal(test, moment([2012, 11, 1]).diff([2013, 11, 1], 'years', true), -1, 'Dec 1 2012 to Dec 1 2013 should be 1 year');191        equal(test, moment([2012, 11, 31]).diff([2013, 11, 31], 'years', true), -1, 'Dec 31 2012 to Dec 31 2013 should be 1 year');192        equal(test, moment([2012, 0, 1]).diff([2013, 6, 1], 'years', true), -1.5, 'Jan 1 2012 to Jul 1 2013 should be 1.5 years');193        equal(test, moment([2012, 0, 31]).diff([2013, 6, 31], 'years', true), -1.5, 'Jan 31 2012 to Jul 31 2013 should be 1.5 years');194        equal(test, moment([2012, 0, 1]).diff([2013, 0, 1, 12], 'years', true), -1 - (0.5 / 31) / 12, 'Jan 1 2012 to Jan 1 2013 noon should be 1+(0.5 / 31) / 12 years');195        equal(test, moment([2012, 0, 1]).diff([2013, 6, 1, 12], 'years', true), -1.5 - (0.5 / 31) / 12, 'Jan 1 2012 to Jul 1 2013 noon should be 1.5+(0.5 / 31) / 12 years');196        equal(test, moment([2012, 1, 29]).diff([2013, 1, 28], 'years', true), -1 + (1 / 28.5) / 12, 'Feb 29 2012 to Feb 28 2013 should be 1-(1 / 28.5) / 12 years');197        test.done();198    }...

Full Screen

Full Screen

diff.qunit.js

Source:diff.qunit.js Github

copy

Full Screen

1/*!2 * ${copyright}3 */4/*global QUnit */5sap.ui.define(['sap/base/util/array/diff'], function(diff) {6	"use strict";7	QUnit.module("diff");8	QUnit.test("simple arrays", function(assert) {9		var aData1 = [1,2,3,4,5];10		var aData2 = [1,4,5,6,7];11		var aData3 = [1,6,7,4,5];12		var aData4 = [1,6,7,2,3];13		var aData5 = [3,4,5,6,7];14		var aData6 = [4,5,7];15		//var aData7 = [9,8,4,4,3,2,9];16		var aData8 = [1,4,5,2,3];17		var aData9 = [1,7,8,9,2,3,4,5];18		var aData10 = [5,4,3,2,1];19		var aData11 = [];20		var aData12 = [1,3,2,5,4];21		var aData13 = [1,2,3,3,3,4,5];22		var aData14 = [3,3,2,1,3,4,5];23		var aData15 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28];24		var aData16 = [3,18,29,30,31,32,33,34,35,36,37];25		var aData17 = [1,2,1,2,1];26		var aData18 = [2,1,2,1,2];27		var aData19 = [1,2,3,4,5,6];28		var aData20 = [1,2,3,4,2,6];29		var aData21 = [1,2,3,4,5,1];30		var aData22 = [8,1,3,1,7,2,6,3,6,9];31		var aData23 = [1,9,7,1,5,9,1,9,9,6];32		var aData24 = [1,2,3,4,2,6,2];33		var aDiff;34		aDiff = [35					{ index: 1, type: 'insert' },36					{ index: 2, type: 'insert' },37					{ index: 3, type: 'insert' },38					{ index: 4, type: 'insert' },39					{ index: 5, type: 'insert' },40					{ index: 8, type: 'delete' },41					{ index: 8, type: 'delete' }42				];43		assert.deepEqual(diff(aData8, aData9), aDiff, "diff between data 8 and 9");44		aDiff = [45					{ index: 1, type: 'delete' },46					{ index: 1, type: 'delete' },47					{ index: 3, type: 'insert' },48					{ index: 4, type: 'insert' }49				];50		assert.deepEqual(diff(aData1, aData2), aDiff, "diff between data 1 and 2");51		aDiff = [52					{ index: 1, type: 'delete' },53					{ index: 1, type: 'delete' },54					{ index: 1, type: 'insert' },55					{ index: 2, type: 'insert' }56				];57		assert.deepEqual(diff(aData1, aData3), aDiff, "diff between data 1 and 3");58		aDiff = [59					{ index: 1, type: 'insert' },60					{ index: 2, type: 'insert' },61					{ index: 5, type: 'delete' },62					{ index: 5, type: 'delete' }63				];64		assert.deepEqual(diff(aData1, aData4), aDiff, "diff between data 1 and 4");65		aDiff = [66					{ index: 1, type: 'insert' },67					{ index: 2, type: 'insert' },68					{ index: 5, type: 'delete' },69					{ index: 5, type: 'delete' }70				];71		assert.deepEqual(diff(aData2, aData3), aDiff, "diff between data 2 and 3");72		aDiff = [73					{ index: 1, type: 'delete' },74					{ index: 1, type: 'delete' },75					{ index: 3, type: 'insert' },76					{ index: 4, type: 'insert' }77				];78		assert.deepEqual(diff(aData2, aData4), aDiff, "diff between data 2 and 4");79		aDiff = [80					{ index: 3, type: 'delete' },81					{ index: 3, type: 'delete' },82					{ index: 3, type: 'insert' },83					{ index: 4, type: 'insert' }84				];85		assert.deepEqual(diff(aData3, aData4), aDiff, "diff between data 3 and 4");86		aDiff = [87					{ index: 0, type: 'delete' },88					{ index: 0, type: 'delete' },89					{ index: 3, type: 'insert' },90					{ index: 4, type: 'insert' }91				];92		assert.deepEqual(diff(aData1, aData5), aDiff, "diff between data 1 and 5");93		aDiff = [94					{ index: 0, type: 'insert' },95					{ index: 1, type: 'insert' },96					{ index: 5, type: 'delete' },97					{ index: 5, type: 'delete' }98				];99		assert.deepEqual(diff(aData5, aData1), aDiff, "diff between data 5 and 1");100		aDiff = [101					{ index: 0, type: 'insert' },102					{ index: 1, type: 'insert' },103					{ index: 2, type: 'insert' },104					{ index: 3, type: 'insert' },105					{ index: 5, type: 'delete' },106					{ index: 5, type: 'delete' },107					{ index: 5, type: 'delete' },108					{ index: 5, type: 'delete' }109				];110		assert.deepEqual(diff(aData1, aData10), aDiff, "diff between data 1 and 10");111		aDiff = [112					{ index: 0, type: 'insert' },113					{ index: 1, type: 'insert' },114					{ index: 2, type: 'insert' },115					{ index: 3, type: 'insert' },116					{ index: 4, type: 'insert' }117				];118		assert.deepEqual(diff(aData11, aData1), aDiff, "diff between data 1 and 11");119		aDiff = [120					{ index: 0, type: 'delete' },121					{ index: 0, type: 'delete' },122					{ index: 0, type: 'delete' },123					{ index: 0, type: 'delete' },124					{ index: 0, type: 'delete' }125				];126		assert.deepEqual(diff(aData1, aData11), aDiff, "diff between data 11 and 1");127		aDiff = [128					{ index: 1, type: 'insert' },129					{ index: 3, type: 'delete' },130					{ index: 3, type: 'insert' },131					{ index: 5, type: 'delete' }132				];133		assert.deepEqual(diff(aData1, aData12), aDiff, "diff between data 1 and 12");134		aDiff = [135					{ index: 0, type: 'insert' },136					{ index: 1, type: 'delete' },137					{ index: 1, type: 'delete' },138					{ index: 2, type: 'insert' },139					{ index: 3, type: 'insert' },140					{ index: 4, type: 'insert' },141					{ index: 5, type: 'insert' },142					{ index: 6, type: 'insert' },143					{ index: 7, type: 'insert' }144				];145		assert.deepEqual(diff(aData6, aData9), aDiff, "diff between data 6 and 9");146		aDiff = [147					{ index: 0, type: 'insert' },148					{ index: 1, type: 'insert' },149					{ index: 2, type: 'insert' },150					{ index: 4, type: 'delete' },151					{ index: 4, type: 'delete' },152					{ index: 4, type: 'delete' }153				];154		assert.deepEqual(diff(aData13, aData14), aDiff, "diff between data 13 and 14");155		aDiff = [156					{ index: 0, type: 'delete' },157					{ index: 0, type: 'delete' },158					{ index: 1, type: 'delete' },159					{ index: 1, type: 'delete' },160					{ index: 1, type: 'delete' },161					{ index: 1, type: 'delete' },162					{ index: 1, type: 'delete' },163					{ index: 1, type: 'delete' },164					{ index: 1, type: 'delete' },165					{ index: 1, type: 'delete' },166					{ index: 1, type: 'delete' },167					{ index: 1, type: 'delete' },168					{ index: 1, type: 'delete' },169					{ index: 1, type: 'delete' },170					{ index: 1, type: 'delete' },171					{ index: 1, type: 'delete' },172					{ index: 2, type: 'delete' },173					{ index: 2, type: 'delete' },174					{ index: 2, type: 'delete' },175					{ index: 2, type: 'delete' },176					{ index: 2, type: 'delete' },177					{ index: 2, type: 'delete' },178					{ index: 2, type: 'delete' },179					{ index: 2, type: 'delete' },180					{ index: 2, type: 'delete' },181					{ index: 2, type: 'delete' },182					{ index: 2, type: 'insert' },183					{ index: 3, type: 'insert' },184					{ index: 4, type: 'insert' },185					{ index: 5, type: 'insert' },186					{ index: 6, type: 'insert' },187					{ index: 7, type: 'insert' },188					{ index: 8, type: 'insert' },189					{ index: 9, type: 'insert' },190					{ index: 10, type: 'insert' }191				];192		assert.deepEqual(diff(aData15, aData16), aDiff, "diff between data 15 and 16");193		aDiff = [194					{ index: 0, type: 'delete' },195					{ index: 0, type: 'delete' },196					{ index: 0, type: 'delete' },197					{ index: 0, type: 'delete' },198					{ index: 0, type: 'delete' },199					{ index: 0, type: 'insert' },200					{ index: 1, type: 'insert' },201					{ index: 2, type: 'insert' },202					{ index: 3, type: 'insert' },203					{ index: 4, type: 'insert' }204				];205		assert.deepEqual(diff(aData17, aData18), aDiff, "diff between data 17 and 18");206		aDiff = [207					{ index: 4, type: 'delete' },208					{ index: 4, type: 'insert' }209				];210		assert.deepEqual(diff(aData19, aData20), aDiff, "diff between data 19 and 20");211		aDiff = [212					{ index: 5, type: 'insert' }213				];214		assert.deepEqual(diff(aData1, aData21), aDiff, "diff between data 1 and 21");215		aDiff = [216					{ index: 0, type: 'delete' },217					{ index: 0, type: 'delete' },218					{ index: 0, type: 'delete' },219					{ index: 0, type: 'delete' },220					{ index: 0, type: 'insert' },221					{ index: 1, type: 'insert' },222					{ index: 3, type: 'delete' },223					{ index: 3, type: 'delete' },224					{ index: 3, type: 'delete' },225					{ index: 3, type: 'delete' },226					{ index: 3, type: 'delete' },227					{ index: 3, type: 'insert' },228					{ index: 4, type: 'insert' },229					{ index: 5, type: 'insert' },230					{ index: 6, type: 'insert' },231					{ index: 7, type: 'insert' },232					{ index: 8, type: 'insert' },233					{ index: 9, type: 'insert' }234				];235		assert.deepEqual(diff(aData22, aData23), aDiff, "diff between data 22 and 23");236		aDiff = [237					{ index: 4, type: 'delete' },238					{ index: 4, type: 'insert' },239					{ index: 6, type: 'insert' }240				];241		assert.deepEqual(diff(aData19, aData24), aDiff, "diff between data 19 and 24");242	});243	QUnit.test("random arrays", function(assert) {244		for (var t = 0; t < 100; t++) {245			var listA = [],246				listB = [],247				listACount = Math.floor(Math.random() * 101),248				listBCount = Math.floor(Math.random() * 101),249				aDiff;250			for (var a = 0; a < listACount; a++) {251				listA[a] = Math.floor(Math.random() * 101);252			}253			for (var b = 0; b < listBCount; b++) {254				listB[b] = Math.floor(Math.random() * 101);255			}256			aDiff = diff(listA, listB);257			for (var d = 0; d < aDiff.length; d++) {258				var oDiff = aDiff[d];259				if (oDiff.type === "insert") {260					listA.splice(oDiff.index, 0, listB[oDiff.index]);261				} else {262					listA.splice(oDiff.index, 1);263				}264			}265			assert.deepEqual(listA, listB, "random arrayDiff " + (t + 1));266		}267	});268	QUnit.test("arrays with undefined values", function(assert) {269		var a1 = [1, 2, 3, undefined],270			a2 = [1, undefined],271			aDiff = diff(a1, a2),272			aResult = [273				{ index: 1, type: 'delete'},274				{ index: 1, type: 'delete'}275			];276		assert.deepEqual(aDiff, aResult, "diff must work with undefined values");277	});...

Full Screen

Full Screen

diff_parser_unittest.py

Source:diff_parser_unittest.py Github

copy

Full Screen

1# Copyright (C) 2009 Google Inc. All rights reserved.2#3# Redistribution and use in source and binary forms, with or without4# modification, are permitted provided that the following conditions are5# met:6#7#    * Redistributions of source code must retain the above copyright8# notice, this list of conditions and the following disclaimer.9#    * Redistributions in binary form must reproduce the above10# copyright notice, this list of conditions and the following disclaimer11# in the documentation and/or other materials provided with the12# distribution.13#    * Neither the name of Google Inc. nor the names of its14# contributors may be used to endorse or promote products derived from15# this software without specific prior written permission.16#17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.28import cStringIO as StringIO29import diff_parser30import re31import unittest32from webkitpy.common.checkout.diff_test_data import DIFF_TEST_DATA33class DiffParserTest(unittest.TestCase):34    maxDiff = None35    def test_diff_parser(self, parser = None):36        if not parser:37            parser = diff_parser.DiffParser(DIFF_TEST_DATA.splitlines())38        self.assertEqual(3, len(parser.files))39        self.assertTrue('WebCore/style/StyleFlexibleBoxData.h' in parser.files)40        diff = parser.files['WebCore/style/StyleFlexibleBoxData.h']41        self.assertEqual(7, len(diff.lines))42        # The first two unchaged lines.43        self.assertEqual((47, 47), diff.lines[0][0:2])44        self.assertEqual('', diff.lines[0][2])45        self.assertEqual((48, 48), diff.lines[1][0:2])46        self.assertEqual('    unsigned align : 3; // EBoxAlignment', diff.lines[1][2])47        # The deleted line48        self.assertEqual((50, 0), diff.lines[3][0:2])49        self.assertEqual('    unsigned orient: 1; // EBoxOrient', diff.lines[3][2])50        # The first file looks OK. Let's check the next, more complicated file.51        self.assertTrue('WebCore/style/StyleRareInheritedData.cpp' in parser.files)52        diff = parser.files['WebCore/style/StyleRareInheritedData.cpp']53        # There are 3 chunks.54        self.assertEqual(7 + 7 + 9, len(diff.lines))55        # Around an added line.56        self.assertEqual((60, 61), diff.lines[9][0:2])57        self.assertEqual((0, 62), diff.lines[10][0:2])58        self.assertEqual((61, 63), diff.lines[11][0:2])59        # Look through the last chunk, which contains both add's and delete's.60        self.assertEqual((81, 83), diff.lines[14][0:2])61        self.assertEqual((82, 84), diff.lines[15][0:2])62        self.assertEqual((83, 85), diff.lines[16][0:2])63        self.assertEqual((84, 0), diff.lines[17][0:2])64        self.assertEqual((0, 86), diff.lines[18][0:2])65        self.assertEqual((0, 87), diff.lines[19][0:2])66        self.assertEqual((85, 88), diff.lines[20][0:2])67        self.assertEqual((86, 89), diff.lines[21][0:2])68        self.assertEqual((87, 90), diff.lines[22][0:2])69        # Check if a newly added file is correctly handled.70        diff = parser.files['LayoutTests/platform/mac/fast/flexbox/box-orient-button-expected.checksum']71        self.assertEqual(1, len(diff.lines))72        self.assertEqual((0, 1), diff.lines[0][0:2])73    def test_diff_converter(self):74        comment_lines = [75            "Hey guys,\n",76            "\n",77            "See my awesome patch below!\n",78            "\n",79            " - Cool Hacker\n",80            "\n",81            ]82        revision_lines = [83            "Subversion Revision 289799\n",84            ]85        svn_diff_lines = [86            "Index: Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",87            "===================================================================\n",88            "--- Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",89            "+++ Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",90            "@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):\n",91            ]92        self.assertEqual(diff_parser.get_diff_converter(svn_diff_lines), diff_parser.svn_diff_to_svn_diff)93        self.assertEqual(diff_parser.get_diff_converter(comment_lines + svn_diff_lines), diff_parser.svn_diff_to_svn_diff)94        self.assertEqual(diff_parser.get_diff_converter(revision_lines + svn_diff_lines), diff_parser.svn_diff_to_svn_diff)95        git_diff_lines = [96            "diff --git a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",97            "index 3c5b45b..0197ead 100644\n",98            "--- a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",99            "+++ b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py\n",100            "@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):\n",101            ]102        self.assertEqual(diff_parser.get_diff_converter(git_diff_lines), diff_parser.git_diff_to_svn_diff)103        self.assertEqual(diff_parser.get_diff_converter(comment_lines + git_diff_lines), diff_parser.git_diff_to_svn_diff)104        self.assertEqual(diff_parser.get_diff_converter(revision_lines + git_diff_lines), diff_parser.git_diff_to_svn_diff)105    def test_git_mnemonicprefix(self):106        p = re.compile(r' ([a|b])/')107        prefixes = [108            { 'a' : 'i', 'b' : 'w' }, # git-diff (compares the (i)ndex and the (w)ork tree)109            { 'a' : 'c', 'b' : 'w' }, # git-diff HEAD (compares a (c)ommit and the (w)ork tree)110            { 'a' : 'c', 'b' : 'i' }, # git diff --cached (compares a (c)ommit and the (i)ndex)111            { 'a' : 'o', 'b' : 'w' }, # git-diff HEAD:file1 file2 (compares an (o)bject and a (w)ork tree entity)112            { 'a' : '1', 'b' : '2' }, # git diff --no-index a b (compares two non-git things (1) and (2))113        ]114        for prefix in prefixes:115            patch = p.sub(lambda x: " %s/" % prefix[x.group(1)], DIFF_TEST_DATA)116            self.test_diff_parser(diff_parser.DiffParser(patch.splitlines()))117    def test_git_diff_to_svn_diff(self):118        output = """\119Index: Tools/Scripts/webkitpy/common/checkout/diff_parser.py120===================================================================121--- Tools/Scripts/webkitpy/common/checkout/diff_parser.py122+++ Tools/Scripts/webkitpy/common/checkout/diff_parser.py123@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):124 A125 B126 C127+D128 E129 F130"""131        inputfmt = StringIO.StringIO("""\132diff --git a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py133index 2ed552c4555db72df16b212547f2c125ae301a04..72870482000c0dba64ce4300ed782c03ee79b74f 100644134--- a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py135+++ b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py136@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):137 A138 B139 C140+D141 E142 F143""")144        shortfmt = StringIO.StringIO("""\145diff --git a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py146index b48b162..f300960 100644147--- a/Tools/Scripts/webkitpy/common/checkout/diff_parser.py148+++ b/Tools/Scripts/webkitpy/common/checkout/diff_parser.py149@@ -59,6 +59,7 @@ def git_diff_to_svn_diff(line):150 A151 B152 C153+D154 E155 F156""")157        self.assertMultiLineEqual(output, ''.join(diff_parser.git_diff_to_svn_diff(x) for x in shortfmt.readlines()))...

Full Screen

Full Screen

index.js

Source:index.js Github

copy

Full Screen

1(function () {2    var settings = allure.getPluginSettings('screen-diff', {diffType: 'diff'});3    function renderImage(src) {4        return '<div class="screen-diff__container">' +5            '<img class="screen-diff__image" src="data/attachments/' + src + '">' +6            '</div>';7    }8    function renderDiffContent(type, data) {9        function findImage(name) {10            if (data.testStage && data.testStage.attachments) {11                return data.testStage.attachments.filter(function (attachment) {12                    return attachment.name === name;13                })[0];14            }15            return null;16        }17        var diffImage = findImage('diff');18        var actualImage = findImage('actual');19        var expectedImage = findImage('expected');20        if (!diffImage && !actualImage && !expectedImage) {21            return '<span>Diff, actual and expected image have not been provided.</span>';22        }23        if (type === 'diff') {24            if (!diffImage) {25                return renderImage(actualImage.source);26            }27            return renderImage(diffImage.source);28        }29        if (type === 'overlay') {30            return '<div class="screen-diff__overlay screen-diff__container">' +31                '<img class="screen-diff__image" src="data/attachments/' + expectedImage.source + '">' +32                '<div class="screen-diff__image-over">' +33                '<img class="screen-diff__image" src="data/attachments/' + actualImage.source + '">' +34                '</div>' +35                '</div>';36        }37    }38    var ScreenDiffView = Backbone.Marionette.View.extend({39        className: 'pane__section',40        events: {41            'click [name="screen-diff-type"]': 'onDiffTypeChange',42            'mousemove .screen-diff__overlay': 'onOverlayMove'43        },44        templateContext: function () {45            return {46                diffType: settings.get('diffType')47            }48        },49        template: function (data) {50            var testType = data.labels.filter(function (label) {51                return label.name === 'testType'52            })[0];53            if (!testType || testType.value !== 'screenshotDiff') {54                return '';55            }56            return '<h3 class="pane__section-title">Screen Diff</h3>' +57                '<div class="screen-diff__content">' +58                '<div class="screen-diff__switchers">' +59                '<label><input type="radio" name="screen-diff-type" value="diff"> Show diff</label>' +60                '<label><input type="radio" name="screen-diff-type" value="overlay"> Show overlay</label>' +61                '</div>' +62                renderDiffContent(data.diffType, data) +63                '</div>';64        },65        adjustImageSize: function (event) {66            var overImage = this.$(event.target);67            overImage.width(overImage.width());68        },69        onRender: function () {70            const diffType = settings.get('diffType');71            this.$('[name="screen-diff-type"][value="' + diffType + '"]').prop('checked', true);72            if (diffType === 'overlay') {73                this.$('.screen-diff__image-over img').on('load', this.adjustImageSize.bind(this));74            }75        },76        onOverlayMove: function (event) {77            var pageX = event.pageX;78            var containerScroll = this.$('.screen-diff__container').scrollLeft();79            var elementX = event.currentTarget.getBoundingClientRect().left;80            var delta = pageX - elementX + containerScroll;81            this.$('.screen-diff__image-over').width(delta);82        },83        onDiffTypeChange: function (event) {84            settings.save('diffType', event.target.value);85            this.render();86        }87    });88    allure.api.addTestResultBlock(ScreenDiffView, {position: 'before'});...

Full Screen

Full Screen

template-diff.js

Source:template-diff.js Github

copy

Full Screen

...4 * Data attributes:5 * - data-plugin="template-diff" - enables the plugin on an element6 *7 * JavaScript API:8 * $('pre').templateDiff({ option: 'value' })9 *10 * Dependences:11 * - jsdiff (diff.js)12 */13+function ($) { "use strict";14    // TEMPALTE DIFF CLASS DEFINITION15    // ============================16    var TemplateDiff = function(element, options) {17        this.options   = options18        this.$el       = $(element)19        // Init20        this.init()21    }22    TemplateDiff.DEFAULTS = {23        oldFieldName: null,24        newFieldName: null,25        contentTag: '',26        diffType: 'lines' // chars, words, lines27    }28    TemplateDiff.prototype.init = function() {29        var30            oldValue = $('[data-field-name="'+this.options.oldFieldName+'"] .form-control '+this.options.contentTag).html(),31            newValue = $('[data-field-name="'+this.options.newFieldName+'"] .form-control '+this.options.contentTag).html()32        oldValue = $('<div />').html(oldValue).text()33        newValue = $('<div />').html(newValue).text()34        this.diffStrings(oldValue, newValue)35    }36    TemplateDiff.prototype.diffStrings = function(oldValue, newValue) {37        var result = this.$el.get(0)38        var diffType = 'diff' + this.options.diffType[0].toUpperCase() + this.options.diffType.slice(1)39        var diff = JsDiff[diffType](oldValue, newValue)40        var fragment = document.createDocumentFragment();41        for (var i=0; i < diff.length; i++) {42            if (diff[i].added && diff[i + 1] && diff[i + 1].removed) {43                var swap = diff[i];44                diff[i] = diff[i + 1];45                diff[i + 1] = swap;46            }47            var node;48            if (diff[i].removed) {49                node = document.createElement('del');50                node.appendChild(document.createTextNode(diff[i].value));51            }52            else if (diff[i].added) {53                node = document.createElement('ins');54                node.appendChild(document.createTextNode(diff[i].value));55            }56            else {57                node = document.createTextNode(diff[i].value);58            }59            fragment.appendChild(node);60        }61        result.textContent = '';62        result.appendChild(fragment);63    }64    // TEMPALTE DIFF PLUGIN DEFINITION65    // ============================66    var old = $.fn.templateDiff67    $.fn.templateDiff = function (option) {68        var args = Array.prototype.slice.call(arguments, 1), result69        this.each(function () {70            var $this   = $(this)71            var data    = $this.data('oc.example')72            var options = $.extend({}, TemplateDiff.DEFAULTS, $this.data(), typeof option == 'object' && option)73            if (!data) $this.data('oc.example', (data = new TemplateDiff(this, options)))74            if (typeof option == 'string') result = data[option].apply(data, args)75            if (typeof result != 'undefined') return false76        })77        78        return result ? result : this79    }80    $.fn.templateDiff.Constructor = TemplateDiff81    // TEMPALTE DIFF NO CONFLICT82    // =================83    $.fn.templateDiff.noConflict = function () {84        $.fn.templateDiff = old85        return this86    }87    // TEMPALTE DIFF DATA-API88    // ===============89    $(document).render(function () {90        $('[data-plugin="template-diff"]').templateDiff()91    });...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1module.exports = {2    {3    },4    {5    }6    {7    }8  paths: {9  },10  engineOptions: {11  },12};13module.exports = async (page, scenario, vp) => {14  await page.type('input[name="email"]', '

Full Screen

Using AI Code Generation

copy

Full Screen

1var backstop = require('backstopjs');2backstop('test');3var backstop = require('backstopjs');4backstop('reference');5var backstop = require('backstopjs');6backstop('approve');7var backstop = require('backstopjs');8backstop('openReport');9var backstop = require('backstopjs');10backstop('openReport');11var backstop = require('backstopjs');12backstop('openReport');13var backstop = require('backstopjs');14backstop('approve');15var backstop = require('backstopjs');16backstop('openReport');17var backstop = require('backstopjs');18backstop('approve');19var backstop = require('backstopjs');20backstop('openReport');21var backstop = require('backstopjs');22backstop('approve');23var backstop = require('backstopjs');24backstop('openReport');25var backstop = require('backstopjs');26backstop('approve');27var backstop = require('backstopjs');28backstop('openReport');29var backstop = require('backstopjs');30backstop('approve');

Full Screen

Using AI Code Generation

copy

Full Screen

1var Backstop = require('backstopjs');2Backstop('test', {config: 'backstop.json'});3{4    {5    },6    {7    },8    {9    },10    {11    }12    {13    }14  "paths": {15  },16  "engineOptions": {17  },18}19var chromy = require('chromy');20chromy.chain()21  .type('input[name="q"]', 'BackstopJS')22  .click('input[name="btnK"]')23  .wait('#resultStats')24  .result(function (result) {25    console.log(result);26  });27var chromy = require('chromy');28chromy.chain()

Full Screen

Using AI Code Generation

copy

Full Screen

1var backstop = require('backstopjs');2backstop('test', {config: 'backstop.json'}).then(function (result) {3  console.log(result);4}).catch(function (error) {5  console.error(error);6});7{8    {9    },10    {11    },12    {13    },14    {15    }16    {17    }18  "paths": {19  },20  "engineOptions": {21  },22}

Full Screen

Using AI Code Generation

copy

Full Screen

1var backstopjs = require('backstopjs');2var backstopjsConfig = require('./backstop.json');3backstopjs('test', {config: backstopjsConfig})4.then(function (result) {5  console.log(result);6  console.log('Test completed');7})8.catch(function (error) {9  console.log(error);10});11{12    {13    },14    {15    }16    {17    }18  "paths": {19  },20  "engineOptions": {21  },22}23docker run --shm-size=1g --rm -it --net=host -v "$(pwd)":/src back

Full Screen

Using AI Code Generation

copy

Full Screen

1var backstopjs = require('backstopjs');2var config = require('./backstop.json');3backstopjs('test', {config: config})4.then(function (result) {5})6.catch(function (err) {7    console.log(err);8});

Full Screen

Using AI Code Generation

copy

Full Screen

1var Backstop = require('backstopjs');2var backstop = new Backstop();3var config = require('./backstop.json');4backstop('test', config).then(function (result) {5  console.log('Test complete');6}, function (error) {7  console.log('Test errored');8  console.log(error);9});10{11    {12    }13    {14    }15  "paths": {16  },17  "engineOptions": {18  },19}20module.exports = async (page, scenario, vp) => {21  console.log('onBefore.js: ' + scenario.label);22  await require('./onReady')(page, scenario, vp);23};24module.exports = async (page, scenario, vp) => {25  console.log('onReady.js: ' + scenario

Full Screen

Using AI Code Generation

copy

Full Screen

1var fs = require('fs');2var diff = require('deep-diff').diff;3var reference = JSON.parse(fs.readFileSync('reference.json'));4var test = JSON.parse(fs.readFileSync('test.json'));5var differences = diff(reference, test);6console.log(differences);7var fs = require('fs');8var diff = require('deep-diff').diff;9var reference = JSON.parse(fs.readFileSync('reference.json'));10var test = JSON.parse(fs.readFileSync('test.json'));11var differences = diff(reference, test);12console.log(differences);13var fs = require('fs');14var diff = require('deep-diff').diff;15var reference = JSON.parse(fs.readFileSync('reference.json'));16var test = JSON.parse(fs.readFileSync('test.json'));17var differences = diff(reference, test);18console.log(differences);19var fs = require('fs');20var diff = require('deep-diff').diff;21var reference = JSON.parse(fs.readFileSync('reference.json'));22var test = JSON.parse(fs.readFileSync('test.json'));23var differences = diff(reference, test);24console.log(differences);25var fs = require('fs');26var diff = require('deep-diff').diff;27var reference = JSON.parse(fs.readFileSync('reference.json'));28var test = JSON.parse(fs.readFileSync('test.json'));29var differences = diff(reference, test);30console.log(differences);31var fs = require('fs');32var diff = require('deep-diff').diff;33var reference = JSON.parse(fs.readFileSync('reference.json'));34var test = JSON.parse(fs.readFileSync('test.json'));35var differences = diff(reference, test);36console.log(differences);37var fs = require('fs');

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run backstopjs automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful