Best JavaScript code snippet using testcafe
diff_match_patch_test.py
Source:diff_match_patch_test.py  
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¶<br></span><del style=\"background:#ffe6e6;\"><B>b</B></del><ins style=\"background:#e6ffe6;\">c&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__":...diff_match_patch_test.js
Source:diff_match_patch_test.js  
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¶<br></span><del style="background:#ffe6e6;"><B>b</B></del><ins style="background:#e6ffe6;">c&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);...fastdiff.js
Source:fastdiff.js  
...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	}...diff.js
Source:diff.js  
...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    }...diff.qunit.js
Source:diff.qunit.js  
...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	});...diff_parser_unittest.py
Source:diff_parser_unittest.py  
...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()))...index.js
Source:index.js  
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'});...template-diff.js
Source:template-diff.js  
1/*2 * Template Diff plugin3 *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    });...Using AI Code Generation
1import { Selector } from 'testcafe';2test('My first test', async t => {3        .typeText('#developer-name', 'John Smith')4        .click('#submit-button')5        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');6});7import { Selector } from 'testcafe';8test('My first test', async t => {9        .typeText('#developer-name', 'John Smith')10        .click('#submit-button')11        .expect(Selector('#article-header').innerText).contains('Thank you, John Smith!');12});13import { Selector } from 'testcafe';14test('My first test', async t => {15        .typeText('#developer-name', 'John Smith')16        .click('#submit-button')17        .expect(Selector('#article-header').innerText).match(/Thank you, John Smith!/);18});19import { Selector } from 'testcafe';20test('My first test', async t => {21        .typeText('#developer-name', 'John Smith')22        .click('#submit-button')23        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');24});25import { Selector } from 'testcafe';26test('My first test', async t => {Using AI Code Generation
1import { Selector } from 'testcafe';2test('My first test', async t => {3        .typeText('#developer-name', 'John Smith')4        .click('#macos')5        .click('#submit-button');6});7import { Selector } from 'testcafe';8import { ClientFunction } from 'testcafe';9test('My first test', async t => {10        .typeText('#developer-name', 'John Smith')11        .click('#macos')12        .click('#submit-button');13    const getLocation = ClientFunction(() => document.location.href);14});Using AI Code Generation
1import { Selector } from 'testcafe';2test('My first test', async t => {3        .typeText('#developer-name', 'John Smith')4        .click('#macos')5        .click('#submit-button');6    const articleHeader = await Selector('.result-content').find('h1');7    let headerText = await articleHeader.innerText;8    let headerDomElement = await articleHeader();9        .expect(headerText).eql('Thank you, John Smith!')10        .expect(headerDomElement.textContent).contains('John');11});Using AI Code Generation
1import { Selector } from 'testcafe';2test('My first test', async t => {3        .typeText('#developer-name', 'John Smith')4        .click('#submit-button')5        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');6});7import { Selector } from 'testcafe';8test('My first test', async t => {9        .typeText('#developer-name', 'John Smith')10        .click('#submit-button')11        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');12});13import { Selector } from 'testcafe';14test('My first test', async t => {15        .typeText('#developer-name', 'John Smith')16        .click('#submit-button')17        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');18});19import { Selector } from 'testcafe';20test('My first test', async t => {21        .typeText('#developer-name', 'John Smith')22        .click('#submit-button')23        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');24});25import { Selector } from 'testcafe';Using AI Code Generation
1import { Selector } from 'testcafe';2test('My first test', async t => {3        .typeText('#developer-name', 'John Smith')4        .click('#submit-button')5        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');6});7import { Selector } from 'testcafe';8test('My first test', async t => {9        .typeText('#developer-name', 'John Smith')10        .click('#submit-button')11        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');12});13import { Selector } from 'testcafe';14test('My first test', async t => {15        .typeText('#developer-name', 'John Smith')16        .click('#submit-button')17        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');18});19import { Selector } from 'testcafe';20test('My first test', async t => {21        .typeText('#developer-name', 'John Smith')22        .click('#submit-button')23        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');24});25import { Selector } from 'testcafe';26test('My first test', async t => {27        .typeText('#developer-name', 'John Smith')28        .click('#submit-button')29        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');30});31import { Selector } from 'testcafe';Using AI Code Generation
1import { Selector } from 'testcafe';2test('My first test', async t => {3        .typeText('#developer-name', 'John Smith')4        .click('#submit-button')5        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');6});7import { Selector } from 'testcafe';8test('My first test', async t => {9        .typeText('#developer-name', 'John Smith')10        .click('#submit-button')11        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');12});13import { Selector } from 'testcafe';14test('My first test', async t => {15        .typeText('#developer-name', 'John Smith')16        .click('#submit-button')17        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');18});19import { Selector } from 'testcafe';20test('My first test', async t => {21        .typeText('#developer-name', 'John Smith')22        .click('#submit-button')23        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');24});25import { Selector } from 'testcafe';26test('My first test', asyncUsing AI Code Generation
1import { Selector } from 'testcafe';2test('My first test', async t => {3        .typeText('#developer-name', 'John Smith')4        .click('#submit-button');5    const articleHeader = await Selector('.result-content').find('h1');6    let headerText = await articleHeader.innerText;7    let id = await articleHeader.id;8    let classAttr = await articleHeader.className;9    let style = await articleHeader.styleProperty('font-family');10    let url = await articleHeader.getAttribute('href');11    let tagName = await articleHeader.tagName;12});Using AI Code Generation
1import { Selector } from 'testcafe';2test('My first test', async t => {3        .typeText('#developer-name', 'John Smith')4        .click('#submit-button')5        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');6});7module.exports = {8};Using AI Code Generation
1import {Selector} from 'testcafe';2test('My first test', async t => {3    const developerName = Selector('#developer-name');4    const osOption = Selector('#macos');5    const submitButton = Selector('#submit-button');6        .typeText(developerName, 'John Smith')7        .click(osOption)8        .click(submitButton)9        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');10});11import {Selector} from 'testcafe';12test('My first test', async t => {13    const developerName = Selector('#developer-name');14    const osOption = Selector('#macos');15    const submitButton = Selector('#submit-button');16        .typeText(developerName, 'John Smith')17        .click(osOption)18        .takeScreenshot('screenshot1.png')19        .click(submitButton)20        .takeScreenshot('screenshot2.png')21        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');22});23import {Selector} from 'testcafe';24test('My first test', async t => {25    const developerName = Selector('#developer-name');26    const osOption = Selector('#macos');27    const submitButton = Selector('#submit-button');28        .typeText(developerName, 'John Smith')29        .takeElementScreenshot(osOption, 'screenshot3.png')30        .click(osOption)31        .takeElementScreenshot(submitButton, 'screenshot4.png')32        .click(submitButton)33        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');34});35import {Selector} from 'testcafe';36test('My first test', async t => {37    const developerName = Selector('#developer-name');Using AI Code Generation
1import {Selector} from 'testcafe';2test('My first test', async t => {3        .typeText('#developer-name', 'John Smith')4        .click('#submit-button')5        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');6});7import {Selector} from 'testcafe';8test('My first test', async t => {9        .typeText('#developer-name', 'John Smith')10        .click('#submit-button')11        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');12});13import {Selector} from 'testcafe';14test('My first test', async t => {15        .typeText('#developer-name', 'John Smith')16        .click('#submit-button')17        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');18});19import {Selector} from 'testcafe';20test('My first test', async t => {21        .typeText('#developer-name', 'John Smith')22        .click('#submit-button')23        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');24});25import {Selector} from 'testcafe';26test('My first test', async t => {27        .typeText('#developer-name', 'John Smith')28        .click('#submit-button')29        .expect(Selector('#article-header').innerText).eql('Thank you, John Smith!');30});31import {Selector} from 'testcafe';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.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
