Repository: stoplightio/spectral
Pull request #2267 (2022-09-06 15:58:57)

fix(core): support utf8 surrogates
Fixes https://github.com/stoplightio/spectral/issues/2265

**Checklist**

- [x] Tests added / updated
- [x] Docs added / updated

**Does this PR introduce a breaking change?**

- [ ] Yes
- [x] No




Patch:
diff --git a/packages/core/package.json b/packages/core/package.json
index 10354090..8e936bf7 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -49,7 +49,6 @@
     "ajv": "^8.6.0",
     "ajv-errors": "~3.0.0",
     "ajv-formats": "~2.1.0",
-    "blueimp-md5": "2.18.0",
     "es-aggregate-error": "^1.0.7",
     "jsonpath-plus": "7.1.0",
     "lodash": "~4.17.21",
diff --git a/packages/core/src/runner/runner.ts b/packages/core/src/runner/runner.ts
index 7a12b524..54b8461b 100644
--- a/packages/core/src/runner/runner.ts
+++ b/packages/core/src/runner/runner.ts
@@ -1,7 +1,7 @@
 import { IDocument } from '../document';
 import { DocumentInventory } from '../documentInventory';
 import { IRuleResult } from '../types';
-import { ComputeFingerprintFunc, prepareResults } from '../utils';
+import { prepareResults } from './utils/results';
 import { lintNode } from './lintNode';
 import { IRunnerInternalContext } from './types';
 import { Ruleset } from '../ruleset/ruleset';
@@ -69,8 +69,8 @@ export class Runner {
     }
   }
 
-  public getResults(computeFingerprint: ComputeFingerprintFunc): IRuleResult[] {
-    return prepareResults(this.results, computeFingerprint);
+  public getResults(): IRuleResult[] {
+    return prepareResults(this.results);
   }
 }
 
diff --git a/packages/core/src/utils/sortResults.ts b/packages/core/src/runner/utils/results.ts
similarity index 57%
rename from packages/core/src/utils/sortResults.ts
rename to packages/core/src/runner/utils/results.ts
index f957ea00..9503a888 100644
--- a/packages/core/src/utils/sortResults.ts
+++ b/packages/core/src/runner/utils/results.ts
@@ -1,5 +1,43 @@
-import { IPosition } from '@stoplight/types';
-import { IRuleResult } from '../types';
+import type { IPosition } from '@stoplight/types';
+import type { ISpectralDiagnostic } from '../../types';
+
+const computeResultFingerprint = (rule: ISpectralDiagnostic): string => {
+  let id = String(rule.code);
+
+  if (rule.path.length > 0) {
+    id += JSON.stringify(rule.path);
+  } else {
+    id += JSON.stringify(rule.range);
+  }
+
+  if (rule.source !== void 0) {
+    id += rule.source;
+  }
+
+  if (rule.message !== void 0) {
+    id += rule.message;
+  }
+
+  return id;
+};
+
+export const prepareResults = (results: ISpectralDiagnostic[]): ISpectralDiagnostic[] => {
+  return sortResults(deduplicateResults(results));
+};
+
+const deduplicateResults = (results: ISpectralDiagnostic[]): ISpectralDiagnostic[] => {
+  const fingerprints = new Set<string>();
+
+  return results.filter(result => {
+    const fingerprint = computeResultFingerprint(result);
+    if (fingerprints.has(fingerprint)) {
+      return false;
+    }
+
+    fingerprints.add(fingerprint);
+    return true;
+  });
+};
 
 const compareCode = (left: string | number | undefined, right: string | number | undefined): number => {
   if (left === void 0 && right === void 0) {
@@ -57,7 +95,7 @@ export const comparePosition = (left: IPosition, right: IPosition): -1 | 0 | 1 =
   return normalize(diffChar);
 };
 
-export const compareResults = (left: IRuleResult, right: IRuleResult): -1 | 0 | 1 => {
+export const compareResults = (left: ISpectralDiagnostic, right: ISpectralDiagnostic): -1 | 0 | 1 => {
   const diffSource = compareSource(left.source, right.source);
 
   if (diffSource !== 0) {
@@ -81,6 +119,6 @@ export const compareResults = (left: IRuleResult, right: IRuleResult): -1 | 0 |
   return normalize(diffPath);
 };
 
-export const sortResults = (results: IRuleResult[]): IRuleResult[] => {
+export const sortResults = (results: ISpectralDiagnostic[]): ISpectralDiagnostic[] => {
   return [...results].sort(compareResults);
 };
diff --git a/packages/core/src/spectral.ts b/packages/core/src/spectral.ts
index 42cb4547..f2a7491c 100644
--- a/packages/core/src/spectral.ts
+++ b/packages/core/src/spectral.ts
@@ -2,21 +2,16 @@ import { stringify } from '@stoplight/json';
 import { DiagnosticSeverity } from '@stoplight/types';
 import * as Parsers from '@stoplight/spectral-parsers';
 import { createHttpAndFileResolver, Resolver } from '@stoplight/spectral-ref-resolver';
-import { memoize } from 'lodash';
 
 import { Document, IDocument, IParsedResult, isParsedResult, ParsedDocument } from './document';
 import { DocumentInventory } from './documentInventory';
 import { Runner } from './runner';
-import { IConstructorOpts, IRunOpts, ISpectralDiagnostic, ISpectralFullResult } from './types';
-import { ComputeFingerprintFunc, defaultComputeResultFingerprint } from './utils';
+import type { IConstructorOpts, IRunOpts, ISpectralDiagnostic, ISpectralFullResult } from './types';
+import type { Format, ParserOptions, RulesetDefinition } from './ruleset/index';
 import { Ruleset } from './ruleset/ruleset';
 import { generateDocumentWideResult } from './utils/generateDocumentWideResult';
-import { ParserOptions, RulesetDefinition } from './ruleset/types';
-import { Format } from './ruleset/format';
 import { getDiagnosticSeverity } from './ruleset';
 
-memoize.Cache = WeakMap;
-
 export * from './types';
 
 export class Spectral {
@@ -24,11 +19,7 @@ export class Spectral {
 
   public ruleset?: Ruleset;
 
-  private readonly _computeFingerprint: ComputeFingerprintFunc;
-
   constructor(protected readonly opts?: IConstructorOpts) {
-    this._computeFingerprint = memoize(defaultComputeResultFingerprint);
-
     if (opts?.resolver !== void 0) {
       this._resolver = opts.resolver;
     } else {
@@ -77,7 +68,7 @@ export class Spectral {
     }
 
     await runner.run(ruleset);
-    const results = runner.getResults(this._computeFingerprint);
+    const results = runner.getResults();
 
     return {
       resolved: inventory.resolved,
diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts
deleted file mode 100644
index 86312bf7..00000000
--- a/packages/core/src/utils/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './prepareResults';
-export * from './sortResults';
diff --git a/packages/core/src/utils/prepareResults.ts b/packages/core/src/utils/prepareResults.ts
deleted file mode 100644
index 4b220fa5..00000000
--- a/packages/core/src/utils/prepareResults.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
-const md5 = require('blueimp-md5');
-
-import { uniqBy } from 'lodash';
-
-import { IRuleResult } from '../types';
-import { compareResults } from './sortResults';
-
-export type ComputeFingerprintFunc = (rule: IRuleResult, hash: (val: string) => string) => string;
-
-export const defaultComputeResultFingerprint: ComputeFingerprintFunc = (rule, hash): string => {
-  let id = String(rule.code);
-
-  if (rule.path.length > 0) {
-    id += JSON.stringify(rule.path);
-  } else {
-    id += JSON.stringify(rule.range);
-  }
-
-  if (rule.source !== void 0) {
-    id += rule.source;
-  }
-
-  if (rule.message !== void 0) {
-    id += rule.message;
-  }
-
-  return hash(id);
-};
-
-export const prepareResults = (results: IRuleResult[], computeFingerprint: ComputeFingerprintFunc): IRuleResult[] => {
-  decorateResultsWithFingerprint(results, computeFingerprint);
-
-  return sortResults(deduplicateResults(results));
-};
-
-const decorateResultsWithFingerprint = (
-  results: IRuleResult[],
-  computeFingerprint: ComputeFingerprintFunc,
-): IRuleResult[] => {
-  for (const r of results) {
-    Object.defineProperty(r, 'fingerprint', {
-      value: computeFingerprint(r, md5),
-    });
-  }
-
-  return results;
-};
-
-const deduplicateResults = (results: IRuleResult[]): IRuleResult[] => {
-  return uniqBy([...results], 'fingerprint');
-};
-
-const sortResults = (results: IRuleResult[]): IRuleResult[] => {
-  return [...results].sort(compareResults);
-};
diff --git a/yarn.lock b/yarn.lock
index b6a58f80..fd456c0d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2566,7 +2566,6 @@ __metadata:
     ajv: ^8.6.0
     ajv-errors: ~3.0.0
     ajv-formats: ~2.1.0
-    blueimp-md5: 2.18.0
     es-aggregate-error: ^1.0.7
     jsonpath-plus: 7.1.0
     lodash: ~4.17.21
@@ -4024,13 +4023,6 @@ __metadata:
   languageName: node
   linkType: hard
 
-"blueimp-md5@npm:2.18.0":
-  version: 2.18.0
-  resolution: "blueimp-md5@npm:2.18.0"
-  checksum: 2f4e5c77af0b322dc0679549bb64c8ab0ebaea729544cd860ec5f8ddb56e781ba446ad7782925cf9a4dec790eb465496b960b8a089ae68b39a720fe7c9c7d36d
-  languageName: node
-  linkType: hard
-
 "bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.1.1, bn.js@npm:^4.11.9":
   version: 4.12.0
   resolution: "bn.js@npm:4.12.0"


Test patch:
diff --git a/packages/core/src/__tests__/linter.test.ts b/packages/core/src/__tests__/linter.test.ts
index a008d423..d1112ec9 100644
--- a/packages/core/src/__tests__/linter.test.ts
+++ b/packages/core/src/__tests__/linter.test.ts
@@ -1326,6 +1326,52 @@ responses:: !!foo
     ]);
   });
 
+  test('should handle utf8 surrogate pairs', async () => {
+    const documentUri = normalize(path.join(__dirname, './__fixtures__/test.json'));
+    const ruleset: RulesetDefinition = {
+      rules: {
+        'valid-type': {
+          given: '$..type',
+          then: {
+            function: truthy,
+          },
+        },
+      },
+    };
+
+    const spectral = new Spectral();
+    spectral.setRuleset(new Ruleset(ruleset, { source: path.join(path.dirname(documentUri), 'ruleset.json') }));
+
+    const document = new Document(
+      JSON.stringify({
+        '\uD87E\uDC04-WORKS': {
+          type: null,
+        },
+        '\uD83D-WORKS-AS-WELL': {
+          type: {
+            foo: {
+              type: null,
+            },
+          },
+        },
+      }),
+      Parsers.Json,
+      documentUri,
+    );
+
+    const results = await spectral.run(document);
+    expect(results).toEqual([
+      expect.objectContaining({
+        code: 'valid-type',
+        path: ['\uD87E\uDC04-WORKS', 'type'],
+      }),
+      expect.objectContaining({
+        code: 'valid-type',
+        path: ['\uD83D-WORKS-AS-WELL', 'type', 'foo', 'type'],
+      }),
+    ]);
+  });
+
   describe('Pointers in overrides', () => {
     test('should be supported', async () => {
       const documentUri = normalize(path.join(__dirname, './__fixtures__/test.json'));
diff --git a/packages/core/src/utils/__tests__/__fixtures__/duplicate-validation-results.json b/packages/core/src/runner/utils/__tests__/__fixtures__/duplicate-validation-results.json
similarity index 100%
rename from packages/core/src/utils/__tests__/__fixtures__/duplicate-validation-results.json
rename to packages/core/src/runner/utils/__tests__/__fixtures__/duplicate-validation-results.json
diff --git a/packages/core/src/utils/__tests__/__fixtures__/non-duplicate-validation-results.json b/packages/core/src/runner/utils/__tests__/__fixtures__/non-duplicate-validation-results.json
similarity index 100%
rename from packages/core/src/utils/__tests__/__fixtures__/non-duplicate-validation-results.json
rename to packages/core/src/runner/utils/__tests__/__fixtures__/non-duplicate-validation-results.json
diff --git a/packages/core/src/runner/utils/__tests__/__fixtures__/random-results.ts b/packages/core/src/runner/utils/__tests__/__fixtures__/random-results.ts
new file mode 100644
index 00000000..3b040507
--- /dev/null
+++ b/packages/core/src/runner/utils/__tests__/__fixtures__/random-results.ts
@@ -0,0 +1,126 @@
+import { DiagnosticSeverity } from '@stoplight/types';
+import type { ISpectralDiagnostic } from '../../../../types';
+
+export const results: ISpectralDiagnostic[] = [
+  {
+    code: 'code 01',
+    path: ['a', 'b', 'c', 'd'],
+    source: 'source 01',
+    range: {
+      start: { line: 1, character: 1 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 01',
+    path: ['a', 'b', 'c', 'd'],
+    source: 'source 02',
+    range: {
+      start: { line: 1, character: 1 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 01',
+    path: ['a', 'b', 'c', 'd'],
+    source: 'source 02',
+    range: {
+      start: { line: 2, character: 1 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 01',
+    path: ['a', 'b', 'c', 'd'],
+    source: 'source 02',
+    range: {
+      start: { line: 2, character: 2 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 02',
+    path: ['a', 'b', 'c', 'd'],
+    source: 'source 02',
+    range: {
+      start: { line: 2, character: 2 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 02',
+    path: ['a', 'b', 'c', 'e'],
+    source: 'source 02',
+    range: {
+      start: { line: 2, character: 2 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 02',
+    path: ['a', 'b', 'c', 'f'],
+    source: 'source 02',
+    range: {
+      start: { line: 2, character: 2 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 03',
+    path: ['a', 'b', 'c', 'f'],
+    source: 'source 02',
+    range: {
+      start: { line: 2, character: 2 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 03',
+    path: ['a', 'b', 'c', 'f'],
+    source: 'source 02',
+    range: {
+      start: { line: 2, character: 3 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 03',
+    path: ['a', 'b', 'c', 'f'],
+    source: 'source 02',
+    range: {
+      start: { line: 3, character: 3 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+  {
+    code: 'code 03',
+    path: ['a', 'b', 'c', 'f'],
+    source: 'source 03',
+    range: {
+      start: { line: 3, character: 3 },
+      end: { line: 99, character: 99 },
+    },
+    message: '99',
+    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+  },
+];
diff --git a/packages/core/src/runner/utils/__tests__/results.test.ts b/packages/core/src/runner/utils/__tests__/results.test.ts
new file mode 100644
index 00000000..97448c63
--- /dev/null
+++ b/packages/core/src/runner/utils/__tests__/results.test.ts
@@ -0,0 +1,162 @@
+import { prepareResults } from '../results';
+import { DiagnosticSeverity, IPosition } from '@stoplight/types';
+
+import { comparePosition, compareResults, sortResults } from '../results';
+import type { ISpectralDiagnostic } from '../../../types';
+
+import duplicateValidationResults from './__fixtures__/duplicate-validation-results.json';
+import { results } from './__fixtures__/random-results';
+
+describe('prepareResults util', () => {
+  it('deduplicate exact validation results', () => {
+    expect(prepareResults(duplicateValidationResults)).toEqual([
+      expect.objectContaining({
+        code: 'valid-example-in-schemas',
+      }),
+      expect.objectContaining({
+        code: 'valid-schema-example-in-content',
+      }),
+    ]);
+  });
+
+  it('deduplicate exact validation results with unknown source', () => {
+    const duplicateValidationResultsWithNoSource = duplicateValidationResults.map(result => ({
+      ...result,
+      source: void 0,
+    }));
+
+    expect(prepareResults(duplicateValidationResultsWithNoSource)).toEqual([
+      expect.objectContaining({
+        code: 'valid-example-in-schemas',
+      }),
+      expect.objectContaining({
+        code: 'valid-schema-example-in-content',
+      }),
+    ]);
+  });
+
+  it('deduplicate list of only duplicates', () => {
+    const onlyDuplicates = [
+      { ...duplicateValidationResults[0] },
+      { ...duplicateValidationResults[0] },
+      { ...duplicateValidationResults[0] },
+      { ...duplicateValidationResults[0] },
+    ];
+
+    expect(prepareResults(onlyDuplicates).length).toBe(1);
+  });
+
+  it('deduplicate only exact validation results', () => {
+    // verifies that results with the same code/path but different messages will not be de-duplicated
+    expect(prepareResults(duplicateValidationResults)).toEqual([
+      expect.objectContaining({
+        code: 'valid-example-in-schemas',
+      }),
+      expect.objectContaining({
+        code: 'valid-schema-example-in-content',
+      }),
+    ]);
+  });
+});
+
+describe('sortResults', () => {
+  const shuffleBy = (arr: ISpectralDiagnostic[], indices: number[]): ISpectralDiagnostic[] => {
+    expect(indices).toHaveLength(arr.length);
+
+    const shuffled = results
+      .map<ISpectralDiagnostic & { pos?: number }>((v, i) => ({ ...v, pos: indices[i] }))
+      .sort((a, b) => a.pos! - b.pos!)
+      .map(v => {
+        delete v.pos;
+        return v;
+      });
+
+    return shuffled;
+  };
+
+  test('should properly order results', () => {
+    const randomlySortedIndices = [5, 4, 1, 10, 8, 6, 3, 9, 2, 0, 7];
+
+    const shuffled = shuffleBy(results, randomlySortedIndices);
+
+    expect(sortResults(shuffled)).toEqual(results);
+  });
+});
+
+describe('compareResults', () => {
+  test('should properly order results source', () => {
+    const input = {
+      code: 'code 01',
+      path: ['a', 'b', 'c', 'd'],
+      range: {
+        start: { line: 1, character: 1 },
+        end: { line: 99, character: 99 },
+      },
+      message: '99',
+      severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+    };
+
+    [
+      { one: void 0, another: void 0, expected: 0 },
+      { one: 'a', another: void 0, expected: 1 },
+      { one: void 0, another: 'a', expected: -1 },
+      { one: 'a', another: 'a', expected: 0 },
+      { one: 'a', another: 'b', expected: -1 },
+    ].forEach(tc => {
+      expect(compareResults({ ...input, source: tc.one }, { ...input, source: tc.another })).toEqual(tc.expected);
+    });
+  });
+
+  test('should properly order results code', () => {
+    const input = {
+      source: 'somewhere',
+      path: ['a', 'b', 'c', 'd'],
+      range: {
+        start: { line: 1, character: 1 },
+        end: { line: 99, character: 99 },
+      },
+      message: '99',
+      severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
+    };
+
+    [
+      { one: 'a', another: 'a', expected: 0 },
+      { one: 'a', another: 'b', expected: -1 },
+      { one: '2', another: '10', expected: -1 },
+      { one: 1, another: 1, expected: 0 },
+      { one: 1, another: 2, expected: -1 },
+      { one: 1, another: '1', expected: 0 },
+      { one: 2, another: '10', expected: -1 },
+    ].forEach(tc => {
+      expect(compareResults({ ...input, code: tc.one }, { ...input, code: tc.another })).toEqual(tc.expected);
+    });
+  });
+});
+
+const buildPosition = (line: number, char: number): IPosition => {
+  return { line, character: char };
+};
+
+describe('comparePosition', () => {
+  const positionTestCases = [
+    [2, 2, 1, 1, 1],
+    [2, 1, 1, 1, 1],
+    [1, 2, 1, 1, 1],
+
+    [1, 1, 1, 1, 0],
+    [1, 2, 1, 2, 0],
+    [2, 1, 2, 1, 0],
+    [2, 2, 2, 2, 0],
+
+    [1, 1, 1, 2, -1],
+    [1, 1, 2, 1, -1],
+    [1, 1, 2, 2, -1],
+  ];
+
+  test.each(positionTestCases)(
+    'should properly order locations (%i, %i) vs (%i, %i)',
+    (leftLine, leftChar, rightLine, rightChar, expected) => {
+      expect(comparePosition(buildPosition(leftLine, leftChar), buildPosition(rightLine, rightChar))).toEqual(expected);
+    },
+  );
+});
diff --git a/packages/core/src/utils/__tests__/prepareResults.test.ts b/packages/core/src/utils/__tests__/prepareResults.test.ts
deleted file mode 100644
index 16ccc73b..00000000
--- a/packages/core/src/utils/__tests__/prepareResults.test.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { defaultComputeResultFingerprint, prepareResults } from '../prepareResults';
-
-import duplicateValidationResults from './__fixtures__/duplicate-validation-results.json';
-
-describe('prepareResults util', () => {
-  it('deduplicate exact validation results', () => {
-    expect(prepareResults(duplicateValidationResults, defaultComputeResultFingerprint)).toEqual([
-      expect.objectContaining({
-        code: 'valid-example-in-schemas',
-      }),
-      expect.objectContaining({
-        code: 'valid-schema-example-in-content',
-      }),
-    ]);
-  });
-
-  it('deduplicate exact validation results with unknown source', () => {
-    const duplicateValidationResultsWithNoSource = duplicateValidationResults.map(result => ({
-      ...result,
-      source: void 0,
-    }));
-
-    expect(prepareResults(duplicateValidationResultsWithNoSource, defaultComputeResultFingerprint)).toEqual([
-      expect.objectContaining({
-        code: 'valid-example-in-schemas',
-      }),
-      expect.objectContaining({
-        code: 'valid-schema-example-in-content',
-      }),
-    ]);
-  });
-
-  it('deduplicate list of only duplicates', () => {
-    const onlyDuplicates = [
-      { ...duplicateValidationResults[0] },
-      { ...duplicateValidationResults[0] },
-      { ...duplicateValidationResults[0] },
-      { ...duplicateValidationResults[0] },
-    ];
-
-    expect(prepareResults(onlyDuplicates, defaultComputeResultFingerprint).length).toBe(1);
-  });
-
-  it('deduplicate only exact validation results', () => {
-    // verifies that results with the same code/path but different messages will not be de-duplicated
-    expect(prepareResults(duplicateValidationResults, defaultComputeResultFingerprint)).toEqual([
-      expect.objectContaining({
-        code: 'valid-example-in-schemas',
-      }),
-      expect.objectContaining({
-        code: 'valid-schema-example-in-content',
-      }),
-    ]);
-  });
-});
diff --git a/packages/core/src/utils/__tests__/sortResults.test.ts b/packages/core/src/utils/__tests__/sortResults.test.ts
deleted file mode 100644
index 3c33871a..00000000
--- a/packages/core/src/utils/__tests__/sortResults.test.ts
+++ /dev/null
@@ -1,229 +0,0 @@
-import { DiagnosticSeverity, IPosition } from '@stoplight/types';
-import { IRuleResult } from '../../types';
-import { comparePosition, compareResults, sortResults } from '../sortResults';
-
-const results: IRuleResult[] = [
-  {
-    code: 'code 01',
-    path: ['a', 'b', 'c', 'd'],
-    source: 'source 01',
-    range: {
-      start: { line: 1, character: 1 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 01',
-    path: ['a', 'b', 'c', 'd'],
-    source: 'source 02',
-    range: {
-      start: { line: 1, character: 1 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 01',
-    path: ['a', 'b', 'c', 'd'],
-    source: 'source 02',
-    range: {
-      start: { line: 2, character: 1 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 01',
-    path: ['a', 'b', 'c', 'd'],
-    source: 'source 02',
-    range: {
-      start: { line: 2, character: 2 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 02',
-    path: ['a', 'b', 'c', 'd'],
-    source: 'source 02',
-    range: {
-      start: { line: 2, character: 2 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 02',
-    path: ['a', 'b', 'c', 'e'],
-    source: 'source 02',
-    range: {
-      start: { line: 2, character: 2 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 02',
-    path: ['a', 'b', 'c', 'f'],
-    source: 'source 02',
-    range: {
-      start: { line: 2, character: 2 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 03',
-    path: ['a', 'b', 'c', 'f'],
-    source: 'source 02',
-    range: {
-      start: { line: 2, character: 2 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 03',
-    path: ['a', 'b', 'c', 'f'],
-    source: 'source 02',
-    range: {
-      start: { line: 2, character: 3 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 03',
-    path: ['a', 'b', 'c', 'f'],
-    source: 'source 02',
-    range: {
-      start: { line: 3, character: 3 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-  {
-    code: 'code 03',
-    path: ['a', 'b', 'c', 'f'],
-    source: 'source 03',
-    range: {
-      start: { line: 3, character: 3 },
-      end: { line: 99, character: 99 },
-    },
-    message: '99',
-    severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-  },
-];
-
-describe('sortResults', () => {
-  const shuffleBy = (arr: IRuleResult[], indices: number[]): IRuleResult[] => {
-    expect(indices).toHaveLength(arr.length);
-
-    const shuffled = results
-      .map<IRuleResult & { pos?: number }>((v, i) => ({ ...v, pos: indices[i] }))
-      .sort((a, b) => a.pos! - b.pos!)
-      .map(v => {
-        delete v.pos;
-        return v;
-      });
-
-    return shuffled;
-  };
-
-  test('should properly order results', () => {
-    const randomlySortedIndices = [5, 4, 1, 10, 8, 6, 3, 9, 2, 0, 7];
-
-    const shuffled = shuffleBy(results, randomlySortedIndices);
-
-    expect(sortResults(shuffled)).toEqual(results);
-  });
-});
-
-describe('compareResults', () => {
-  test('should properly order results source', () => {
-    const input = {
-      code: 'code 01',
-      path: ['a', 'b', 'c', 'd'],
-      range: {
-        start: { line: 1, character: 1 },
-        end: { line: 99, character: 99 },
-      },
-      message: '99',
-      severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-    };
-
-    [
-      { one: void 0, another: void 0, expected: 0 },
-      { one: 'a', another: void 0, expected: 1 },
-      { one: void 0, another: 'a', expected: -1 },
-      { one: 'a', another: 'a', expected: 0 },
-      { one: 'a', another: 'b', expected: -1 },
-    ].forEach(tc => {
-      expect(compareResults({ ...input, source: tc.one }, { ...input, source: tc.another })).toEqual(tc.expected);
-    });
-  });
-
-  test('should properly order results code', () => {
-    const input = {
-      source: 'somewhere',
-      path: ['a', 'b', 'c', 'd'],
-      range: {
-        start: { line: 1, character: 1 },
-        end: { line: 99, character: 99 },
-      },
-      message: '99',
-      severity: DiagnosticSeverity.Error, // or any other level, it's irrelevant
-    };
-
-    [
-      { one: 'a', another: 'a', expected: 0 },
-      { one: 'a', another: 'b', expected: -1 },
-      { one: '2', another: '10', expected: -1 },
-      { one: 1, another: 1, expected: 0 },
-      { one: 1, another: 2, expected: -1 },
-      { one: 1, another: '1', expected: 0 },
-      { one: 2, another: '10', expected: -1 },
-    ].forEach(tc => {
-      expect(compareResults({ ...input, code: tc.one }, { ...input, code: tc.another })).toEqual(tc.expected);
-    });
-  });
-});
-
-const buildPosition = (line: number, char: number): IPosition => {
-  return { line, character: char };
-};
-
-describe('comparePosition', () => {
-  const positionTestCases = [
-    [2, 2, 1, 1, 1],
-    [2, 1, 1, 1, 1],
-    [1, 2, 1, 1, 1],
-
-    [1, 1, 1, 1, 0],
-    [1, 2, 1, 2, 0],
-    [2, 1, 2, 1, 0],
-    [2, 2, 2, 2, 0],
-
-    [1, 1, 1, 2, -1],
-    [1, 1, 2, 1, -1],
-    [1, 1, 2, 2, -1],
-  ];
-
-  test.each(positionTestCases)(
-    'should properly order locations (%i, %i) vs (%i, %i)',
-    (leftLine, leftChar, rightLine, rightChar, expected) => {
-      expect(comparePosition(buildPosition(leftLine, leftChar), buildPosition(rightLine, rightChar))).toEqual(expected);
-    },
-  );
-});