How to use Diff method in backstopjs

Best JavaScript code snippet using backstopjs

diff_match_patch_test.py

Source:diff_match_patch_test.py Github

copy

Full Screen

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

Full Screen

Full Screen

diff_match_patch_test.js

Source:diff_match_patch_test.js Github

copy

Full Screen

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

Full Screen

Full Screen

fastdiff.js

Source:fastdiff.js Github

copy

Full Screen

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

Full Screen

Full Screen

diff.js

Source:diff.js Github

copy

Full Screen

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

Full Screen

Full Screen

diff.qunit.js

Source:diff.qunit.js Github

copy

Full Screen

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

Full Screen

Full Screen

diff_parser_unittest.py

Source:diff_parser_unittest.py Github

copy

Full Screen

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

Full Screen

Full Screen

index.js

Source:index.js Github

copy

Full Screen

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

Full Screen

Full Screen

template-diff.js

Source:template-diff.js Github

copy

Full Screen

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

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Automation Testing Tutorials

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

LambdaTest Learning Hubs:

YouTube

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

Run backstopjs automation tests on LambdaTest cloud grid

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

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful