addons/shared/createTokenizedIntralineDiff.test.tsxblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {HighlightedToken} from './textmate-lib/tokenize';
b69ab319
b69ab3110import {
b69ab3111 createTokenizedIntralineDiff,
b69ab3112 MAX_INPUT_LENGTH_FOR_INTRALINE_DIFF,
b69ab3113} from './createTokenizedIntralineDiff';
b69ab3114
b69ab3115describe('createTokenizedIntralineDiff', () => {
b69ab3116 test('empty string', () => {
b69ab3117 const beforeLine = '';
b69ab3118 const beforeTokens: HighlightedToken[] = [];
b69ab3119 const afterLine = '';
b69ab3120 const afterTokens: HighlightedToken[] = [];
b69ab3121 const [left, right] = createTokenizedIntralineDiff(
b69ab3122 beforeLine,
b69ab3123 beforeTokens,
b69ab3124 afterLine,
b69ab3125 afterTokens,
b69ab3126 );
b69ab3127 expect(left).toBe(null);
b69ab3128 expect(right).toBe(null);
b69ab3129 });
b69ab3130
b69ab3131 test('diff on words, not chars', () => {
b69ab3132 const beforeLine = 'global x';
b69ab3133 const beforeTokens = [
b69ab3134 {start: 0, end: 6, color: 2},
b69ab3135 {start: 6, end: 7, color: 1},
b69ab3136 {start: 7, end: 8, color: 3},
b69ab3137 ];
b69ab3138 const afterLine = 'nonlocal xyz';
b69ab3139 const afterTokens = [
b69ab3140 {start: 0, end: 8, color: 2},
b69ab3141 {start: 8, end: 9, color: 1},
b69ab3142 {start: 9, end: 12, color: 3},
b69ab3143 ];
b69ab3144 const [left, right] = createTokenizedIntralineDiff(
b69ab3145 beforeLine,
b69ab3146 beforeTokens,
b69ab3147 afterLine,
b69ab3148 afterTokens,
b69ab3149 );
b69ab3150 expect(left).toEqual([
b69ab3151 <span key={0} className="mtk2 patch-remove-word patch-word-begin patch-word-end">
b69ab3152 global
b69ab3153 </span>,
b69ab3154 <span key={6} className="mtk1">
b69ab3155 {' '}
b69ab3156 </span>,
b69ab3157 <span key={7} className="mtk3 patch-remove-word patch-word-begin patch-word-end">
b69ab3158 x
b69ab3159 </span>,
b69ab3160 ]);
b69ab3161 expect(right).toEqual([
b69ab3162 <span key={0} className="mtk2 patch-add-word patch-word-begin patch-word-end">
b69ab3163 nonlocal
b69ab3164 </span>,
b69ab3165 <span key={8} className="mtk1">
b69ab3166 {' '}
b69ab3167 </span>,
b69ab3168 <span key={9} className="mtk3 patch-add-word patch-word-begin patch-word-end">
b69ab3169 xyz
b69ab3170 </span>,
b69ab3171 ]);
b69ab3172 });
b69ab3173
b69ab3174 test('renamed variable', () => {
b69ab3175 const beforeLine = 'func _unhandled_input(event: InputEvent) -> void:';
b69ab3176 const beforeTokens = [
b69ab3177 {start: 0, end: 4, color: 4},
b69ab3178 {start: 4, end: 5, color: 1},
b69ab3179 {start: 5, end: 21, color: 10},
b69ab3180 {start: 21, end: 29, color: 1},
b69ab3181 {start: 29, end: 39, color: 9},
b69ab3182 {start: 39, end: 44, color: 1},
b69ab3183 {start: 44, end: 48, color: 9},
b69ab3184 {start: 48, end: 49, color: 1},
b69ab3185 ];
b69ab3186 const afterLine = 'func _unhandled_input(input_event: InputEvent) -> void:';
b69ab3187 const afterTokens = [
b69ab3188 {start: 0, end: 4, color: 4},
b69ab3189 {start: 4, end: 5, color: 1},
b69ab3190 {start: 5, end: 21, color: 10},
b69ab3191 {start: 21, end: 35, color: 1},
b69ab3192 {start: 35, end: 45, color: 9},
b69ab3193 {start: 45, end: 50, color: 1},
b69ab3194 {start: 50, end: 54, color: 9},
b69ab3195 {start: 54, end: 55, color: 1},
b69ab3196 ];
b69ab3197 const [left, right] = createTokenizedIntralineDiff(
b69ab3198 beforeLine,
b69ab3199 beforeTokens,
b69ab31100 afterLine,
b69ab31101 afterTokens,
b69ab31102 );
b69ab31103 expect(left).toEqual([
b69ab31104 <span key={0} className="mtk4">
b69ab31105 func
b69ab31106 </span>,
b69ab31107 <span key={4} className="mtk1">
b69ab31108 {' '}
b69ab31109 </span>,
b69ab31110 <span key={5} className="mtk10">
b69ab31111 _unhandled_input
b69ab31112 </span>,
b69ab31113 <span key={21} className="mtk1">
b69ab31114 (
b69ab31115 </span>,
b69ab31116 <span key={22} className="mtk1 patch-remove-word patch-word-begin patch-word-end">
b69ab31117 event
b69ab31118 </span>,
b69ab31119 <span key={27} className="mtk1">
b69ab31120 {': '}
b69ab31121 </span>,
b69ab31122 <span key={29} className="mtk9">
b69ab31123 InputEvent
b69ab31124 </span>,
b69ab31125 <span key={39} className="mtk1">
b69ab31126 {') -> '}
b69ab31127 </span>,
b69ab31128 <span key={44} className="mtk9">
b69ab31129 void
b69ab31130 </span>,
b69ab31131 <span key={48} className="mtk1">
b69ab31132 :
b69ab31133 </span>,
b69ab31134 ]);
b69ab31135 expect(right).toEqual([
b69ab31136 <span key={0} className="mtk4">
b69ab31137 func
b69ab31138 </span>,
b69ab31139 <span key={4} className="mtk1">
b69ab31140 {' '}
b69ab31141 </span>,
b69ab31142 <span key={5} className="mtk10">
b69ab31143 _unhandled_input
b69ab31144 </span>,
b69ab31145 <span key={21} className="mtk1">
b69ab31146 (
b69ab31147 </span>,
b69ab31148 <span key={22} className="mtk1 patch-add-word patch-word-begin patch-word-end">
b69ab31149 input_event
b69ab31150 </span>,
b69ab31151 <span key={33} className="mtk1">
b69ab31152 {': '}
b69ab31153 </span>,
b69ab31154 <span key={35} className="mtk9">
b69ab31155 InputEvent
b69ab31156 </span>,
b69ab31157 <span key={45} className="mtk1">
b69ab31158 {') -> '}
b69ab31159 </span>,
b69ab31160 <span key={50} className="mtk9">
b69ab31161 void
b69ab31162 </span>,
b69ab31163 <span key={54} className="mtk1">
b69ab31164 :
b69ab31165 </span>,
b69ab31166 ]);
b69ab31167 });
b69ab31168
b69ab31169 test('diffing unrelated lines', () => {
b69ab31170 const beforeLine = '# - event: Triggered event';
b69ab31171 const beforeTokens = [{start: 0, end: 26, color: 3}];
b69ab31172 const afterLine = 'func _unhandled_input(input_event: InputEvent) -> void:';
b69ab31173 const afterTokens = [
b69ab31174 {start: 0, end: 4, color: 4},
b69ab31175 {start: 4, end: 5, color: 1},
b69ab31176 {start: 5, end: 21, color: 10},
b69ab31177 {start: 21, end: 35, color: 1},
b69ab31178 {start: 35, end: 45, color: 9},
b69ab31179 {start: 45, end: 50, color: 1},
b69ab31180 {start: 50, end: 54, color: 9},
b69ab31181 {start: 54, end: 55, color: 1},
b69ab31182 ];
b69ab31183 const [left, right] = createTokenizedIntralineDiff(
b69ab31184 beforeLine,
b69ab31185 beforeTokens,
b69ab31186 afterLine,
b69ab31187 afterTokens,
b69ab31188 );
b69ab31189 expect(left).toEqual([
b69ab31190 <span key={0} className="mtk3 patch-remove-word patch-word-begin patch-word-end">
b69ab31191 {'#'}
b69ab31192 </span>,
b69ab31193 <span key={1} className="mtk3">
b69ab31194 {' '}
b69ab31195 </span>,
b69ab31196 <span key={2} className="mtk3 patch-remove-word patch-word-begin patch-word-end">
b69ab31197 {'- event'}
b69ab31198 </span>,
b69ab31199 <span key={9} className="mtk3">
b69ab31200 {': '}
b69ab31201 </span>,
b69ab31202 <span key={11} className="mtk3 patch-remove-word patch-word-begin patch-word-end">
b69ab31203 {'Triggered'}
b69ab31204 </span>,
b69ab31205 <span key={20} className="mtk3">
b69ab31206 {' '}
b69ab31207 </span>,
b69ab31208 <span key={21} className="mtk3 patch-remove-word patch-word-begin patch-word-end">
b69ab31209 {'event'}
b69ab31210 </span>,
b69ab31211 ]);
b69ab31212 expect(right).toEqual([
b69ab31213 <span key={0} className="mtk4 patch-add-word patch-word-begin patch-word-end">
b69ab31214 func
b69ab31215 </span>,
b69ab31216 <span key={4} className="mtk1">
b69ab31217 {' '}
b69ab31218 </span>,
b69ab31219 <span key={5} className="mtk10 patch-add-word patch-word-begin">
b69ab31220 _unhandled_input
b69ab31221 </span>,
b69ab31222 <span key={21} className="mtk1 patch-add-word patch-word-end">
b69ab31223 {'(input_event'}
b69ab31224 </span>,
b69ab31225 <span key={33} className="mtk1">
b69ab31226 {': '}
b69ab31227 </span>,
b69ab31228 <span key={35} className="mtk9 patch-add-word patch-word-begin">
b69ab31229 InputEvent
b69ab31230 </span>,
b69ab31231 <span key={45} className="mtk1 patch-add-word patch-word-end">
b69ab31232 {')'}
b69ab31233 </span>,
b69ab31234 <span key={46} className="mtk1">
b69ab31235 {' '}
b69ab31236 </span>,
b69ab31237 <span key={47} className="mtk1 patch-add-word patch-word-begin">
b69ab31238 {'-> '}
b69ab31239 </span>,
b69ab31240 <span key={50} className="mtk9 patch-add-word">
b69ab31241 void
b69ab31242 </span>,
b69ab31243 <span key={54} className="mtk1 patch-add-word patch-word-end">
b69ab31244 :
b69ab31245 </span>,
b69ab31246 ]);
b69ab31247 });
b69ab31248
b69ab31249 test('first patch-remove-work chunk has multiple tokens', () => {
b69ab31250 const beforeLine = ' return true;';
b69ab31251 const beforeTokens = [
b69ab31252 {start: 0, end: 4, color: 1},
b69ab31253 {start: 4, end: 10, color: 4},
b69ab31254 {start: 10, end: 11, color: 1},
b69ab31255 {start: 11, end: 15, color: 9},
b69ab31256 {start: 15, end: 16, color: 1},
b69ab31257 ];
b69ab31258 const afterLine = '';
b69ab31259 const afterTokens = [{start: 0, end: 0, color: 1}];
b69ab31260 const [left, right] = createTokenizedIntralineDiff(
b69ab31261 beforeLine,
b69ab31262 beforeTokens,
b69ab31263 afterLine,
b69ab31264 afterTokens,
b69ab31265 );
b69ab31266 expect(left).toEqual([
b69ab31267 <span key={0} className="mtk1 patch-remove-word patch-word-begin">
b69ab31268 {' '}
b69ab31269 </span>,
b69ab31270 <span key={4} className="mtk4 patch-remove-word">
b69ab31271 return
b69ab31272 </span>,
b69ab31273 <span key={10} className="mtk1 patch-remove-word">
b69ab31274 {' '}
b69ab31275 </span>,
b69ab31276 <span key={11} className="mtk9 patch-remove-word">
b69ab31277 true
b69ab31278 </span>,
b69ab31279 <span key={15} className="mtk1 patch-remove-word patch-word-end">
b69ab31280 ;
b69ab31281 </span>,
b69ab31282 ]);
b69ab31283 expect(right).toEqual([]);
b69ab31284 });
b69ab31285
b69ab31286 test('creating an intraline diff for a line that is too long should bail out', () => {
b69ab31287 // We repeat a piece of text with a space because createTokenizedIntralineDiff()
b69ab31288 // uses diffWords() under the hood.
b69ab31289 const beforeLine = 'reviewstack '.repeat(12);
b69ab31290 const beforeTokens = [{start: 0, end: beforeLine.length, color: 1}];
b69ab31291 const afterLineAtThreshold = 'reviewstack '.repeat(13);
b69ab31292 expect(beforeLine.length + afterLineAtThreshold.length).toBe(
b69ab31293 MAX_INPUT_LENGTH_FOR_INTRALINE_DIFF,
b69ab31294 );
b69ab31295 const afterTokensAtThreshold = [{start: 0, end: afterLineAtThreshold.length, color: 1}];
b69ab31296 const [leftAtThreshold, rightAtThreshold] = createTokenizedIntralineDiff(
b69ab31297 beforeLine,
b69ab31298 beforeTokens,
b69ab31299 afterLineAtThreshold,
b69ab31300 afterTokensAtThreshold,
b69ab31301 );
b69ab31302 expect(leftAtThreshold).toEqual([
b69ab31303 <span key={0} className="mtk1">
b69ab31304 {beforeLine}
b69ab31305 </span>,
b69ab31306 ]);
b69ab31307 expect(rightAtThreshold).toEqual([
b69ab31308 <span key={0} className="mtk1">
b69ab31309 {beforeLine}
b69ab31310 </span>,
b69ab31311 <span key={beforeLine.length} className="mtk1 patch-add-word patch-word-begin patch-word-end">
b69ab31312 {'reviewstack '}
b69ab31313 </span>,
b69ab31314 ]);
b69ab31315
b69ab31316 // Verify that once the input exceeds the threshold, we no longer see CSS
b69ab31317 // classes like patch-word-begin or patch-word-end in the output, indicating
b69ab31318 // that the inline diff was not computed.
b69ab31319 const afterLineOneLonger = afterLineAtThreshold + 'X';
b69ab31320 expect(beforeLine.length + afterLineOneLonger.length).toBeGreaterThan(
b69ab31321 MAX_INPUT_LENGTH_FOR_INTRALINE_DIFF,
b69ab31322 );
b69ab31323 const afterTokensOneLonger = [{start: 0, end: afterLineOneLonger.length, color: 1}];
b69ab31324 const [leftOneLonger, rightOneLonger] = createTokenizedIntralineDiff(
b69ab31325 beforeLine,
b69ab31326 beforeTokens,
b69ab31327 afterLineOneLonger,
b69ab31328 afterTokensOneLonger,
b69ab31329 );
b69ab31330 expect(leftOneLonger).toEqual([
b69ab31331 <span key={0} className="mtk1">
b69ab31332 {beforeLine}
b69ab31333 </span>,
b69ab31334 ]);
b69ab31335 expect(rightOneLonger).toEqual([
b69ab31336 <span key={0} className="mtk1">
b69ab31337 {afterLineOneLonger}
b69ab31338 </span>,
b69ab31339 ]);
b69ab31340 });
b69ab31341
b69ab31342 test('diffWordsWithSpace() must be used instead of diffWords() or content will be lost', () => {
b69ab31343 const beforeLine = ' <SplitDiffRow';
b69ab31344 const afterLine = ' path,';
b69ab31345 const beforeTokens = [
b69ab31346 {start: 0, end: 8, color: 1},
b69ab31347 {start: 8, end: 9, color: 13},
b69ab31348 {start: 9, end: 21, color: 9},
b69ab31349 ];
b69ab31350 const afterTokens = [
b69ab31351 {start: 0, end: 6, color: 1},
b69ab31352 {start: 6, end: 10, color: 14},
b69ab31353 {start: 10, end: 11, color: 1},
b69ab31354 ];
b69ab31355 const [left, right] = createTokenizedIntralineDiff(
b69ab31356 beforeLine,
b69ab31357 beforeTokens,
b69ab31358 afterLine,
b69ab31359 afterTokens,
b69ab31360 );
b69ab31361 expect(left).toEqual([
b69ab31362 <span key={0} className="mtk1 patch-remove-word patch-word-begin">
b69ab31363 {' '}
b69ab31364 </span>,
b69ab31365 <span key={8} className="mtk13 patch-remove-word">
b69ab31366 {'<'}
b69ab31367 </span>,
b69ab31368 <span key={9} className="mtk9 patch-remove-word patch-word-end">
b69ab31369 {'SplitDiffRow'}
b69ab31370 </span>,
b69ab31371 ]);
b69ab31372 expect(right).toEqual([
b69ab31373 <span key={0} className="mtk1 patch-add-word patch-word-begin">
b69ab31374 {' '}
b69ab31375 </span>,
b69ab31376 <span key={6} className="mtk14 patch-add-word">
b69ab31377 path
b69ab31378 </span>,
b69ab31379 <span key={10} className="mtk1 patch-add-word patch-word-end">
b69ab31380 {','}
b69ab31381 </span>,
b69ab31382 ]);
b69ab31383 });
b69ab31384});