All files / diff/src/__tests__ util.ts

100% Statements 53/53
92% Branches 23/25
100% Functions 7/7
100% Lines 41/41

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 8210x             10x             3839x             10x 27817x 27817x 1900671x 1900671x 38788x 38762x 38762x 38229x 1861883x   26617x     10x   4221x 4221x 24633x 24633x 24633x     4221x 18659x   4221x 4221x 4221x 4221x       8130x     7862x     4221x 4221x 4221x 4221x 4221x       7862x     8130x     4221x 4221x 4221x 4221x 4221x 4221x    
import * as diff from '../str';
 
/**
 * The fuzz and stress suites run reduced round counts and input sizes by
 * default, so that a full `yarn test` stays quick. `RUN_SLOW_TESTS=1` restores
 * the full-size run: the same shapes, the numbers they were written at.
 */
export const slow = !!process.env.RUN_SLOW_TESTS && process.env.RUN_SLOW_TESTS !== '0';
 
/**
 * Rounds a randomised property should run. Every round draws a fresh shape, so
 * the count buys breadth rather than depth: a third of it still walks the same
 * generators. `RUN_SLOW_TESTS=1` runs the counts these were written at.
 */
export const rounds = (full: number): number => (slow ? full : Math.ceil(full / 3));
 
/**
 * Checks that a string is well-formed UTF-16: every high surrogate is
 * immediately followed by a low surrogate, and there are no unpaired low
 * surrogates.
 */
export const isWellFormed = (str: string): boolean => {
  const length = str.length;
  for (let i = 0; i < length; i++) {
    const code = str.charCodeAt(i);
    if (code >= 0xd800 && code <= 0xdbff) {
      if (i + 1 >= length) return false;
      const next = str.charCodeAt(i + 1);
      if (next < 0xdc00 || next > 0xdfff) return false;
      i++;
    } else if (code >= 0xdc00 && code <= 0xdfff) return false;
  }
  return true;
};
 
export const assertPatch = (src: string, dst: string, patch: diff.Patch = diff.diff(src, dst)) => {
  // Patch is normalized: no op has empty text, no two adjacent ops share a type.
  const patchLength = patch.length;
  for (let i = 0; i < patchLength; i++) {
    const op = patch[i];
    expect(op[1].length).toBeGreaterThan(0);
    if (i > 0) expect(op[0]).not.toBe(patch[i - 1][0]);
  }
  // If both inputs are well-formed UTF-16, every op text must be well-formed.
  if (isWellFormed(src) && isWellFormed(dst)) {
    for (let i = 0; i < patchLength; i++) expect(isWellFormed(patch[i][1])).toBe(true);
  }
  const src1 = diff.src(patch);
  const dst1 = diff.dst(patch);
  let dst2 = src;
  diff.apply(
    patch,
    dst2.length,
    (pos, str) => {
      dst2 = dst2.slice(0, pos) + str + dst2.slice(pos);
    },
    (pos, len) => {
      dst2 = dst2.slice(0, pos) + dst2.slice(pos + len);
    },
  );
  const inverted = diff.invert(patch);
  const src2 = diff.dst(inverted);
  const dst3 = diff.src(inverted);
  let src3 = dst;
  diff.apply(
    inverted,
    src3.length,
    (pos, str) => {
      src3 = src3.slice(0, pos) + str + src3.slice(pos);
    },
    (pos, len) => {
      src3 = src3.slice(0, pos) + src3.slice(pos + len);
    },
  );
  expect(src1).toBe(src);
  expect(src2).toBe(src);
  expect(src3).toBe(src);
  expect(dst1).toBe(dst);
  expect(dst2).toBe(dst);
  expect(dst3).toBe(dst);
};