Repository: stoplightio/spectral
Pull request #1473 (2021-01-12 23:14:02)

test(asyncapi): align tests with oas 
Extracted from https://github.com/stoplightio/spectral/pull/1470
Related to #1082 
Complementary PR to https://github.com/stoplightio/spectral/pull/1472
It moves us one step ahead towards monorepo.


**Checklist**

- [x] Tests added / updated
- [x] Docs added / updated

**Does this PR introduce a breaking change?**

- [ ] Yes
- [x] No




Patch:
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index c4de087a..83837c8c 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -25,12 +25,12 @@ jobs:
       - script: yarn
         displayName: Install deps
 
-      - script: yarn lint
-        displayName: Lint the code
-
       - script: yarn build
         displayName: Build the code in JavaScript
 
+      - script: yarn lint
+        displayName: Lint the code
+
       - script: yarn test.karma
         displayName: Run the browser tests
 
diff --git a/jest.config.js b/jest.config.js
index dbbd37ec..0fe124e2 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -3,8 +3,8 @@ module.exports = {
   moduleFileExtensions: ['ts', 'tsx', 'js'],
   testEnvironment: 'node',
   testMatch: ['<rootDir>/src/**/__tests__/*.(ts)'],
-  testPathIgnorePatterns: ['/node_modules/', '\.karma\.test\.ts$'],
+  testPathIgnorePatterns: ['/node_modules/', '.karma.test.ts$'],
   coveragePathIgnorePatterns: ['<rootDir>/dist/', '/node_modules/'],
-  setupFilesAfterEnv: ['./setupJest.ts', './setupTests.ts'],
-  globalSetup: './setupJest.global.ts'
+  setupFilesAfterEnv: ['./setupJest.ts'],
+  globalSetup: './setupJest.global.ts',
 };


Test patch:
diff --git a/setupTests.ts b/setupTests.ts
deleted file mode 100644
index b5b133ba..00000000
--- a/setupTests.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { RulesetExceptionCollection } from './src/types/ruleset';
-
-import { IRule, isAsyncApiv2, Rule, RuleCollection, Spectral } from './src';
-import { rules as asyncApiRules } from './src/rulesets/asyncapi/index.json';
-
-export const buildRulesetExceptionCollectionFrom = (
-  loc: string,
-  rules: string[] = ['a'],
-): RulesetExceptionCollection => {
-  const source = {};
-  source[loc] = rules;
-  return source;
-};
-
-const removeAllRulesBut = (spectral: Spectral, ruleName: string) => {
-  expect(Object.keys(spectral.rules)).toContain(ruleName);
-
-  const rule1 = spectral.rules[ruleName];
-
-  const rawRule = asyncApiRules[ruleName];
-
-  const patchedRule = Object.assign(rule1, {
-    recommended: true,
-    severity: rawRule.severity,
-  }) as IRule;
-
-  const rules: RuleCollection = {};
-  rules[ruleName] = patchedRule;
-  spectral.setRules(rules);
-};
-
-export const buildTestSpectralWithAsyncApiRule = async (ruleName: string): Promise<[Spectral, Rule]> => {
-  const s = new Spectral();
-  s.registerFormat('asyncapi2', isAsyncApiv2);
-  await s.loadRuleset('spectral:asyncapi');
-
-  removeAllRulesBut(s, ruleName);
-  expect(Object.keys(s.rules)).toEqual([ruleName]);
-
-  const rule = s.rules[ruleName];
-  expect(rule.enabled).not.toBe(false);
-  expect(rule.severity).not.toBeUndefined();
-  expect(rule.severity).not.toEqual(-1);
-  expect(rule.formats).not.toBeUndefined();
-  expect(rule.formats).toContain('asyncapi2');
-
-  return [s, rule];
-};
diff --git a/src/__tests__/spectral.test.ts b/src/__tests__/spectral.test.ts
index 51325510..d80bc631 100644
--- a/src/__tests__/spectral.test.ts
+++ b/src/__tests__/spectral.test.ts
@@ -3,7 +3,6 @@ import { DiagnosticSeverity } from '@stoplight/types';
 import { DepGraph } from 'dependency-graph';
 import { escapeRegExp, merge } from 'lodash';
 
-import { buildRulesetExceptionCollectionFrom } from '../../setupTests';
 import { Document } from '../document';
 import * as Parsers from '../parsers';
 import { RunRuleCollection, Spectral } from '../spectral';
@@ -282,7 +281,7 @@ describe('spectral', () => {
       it.each([['one.yaml#'], ['one.yaml#/'], ['one.yaml#/toto'], ['down/one.yaml#/toto'], ['../one.yaml#/toto']])(
         'throws on relative locations  (location: "%s")',
         location => {
-          const exceptions = buildRulesetExceptionCollectionFrom(location);
+          const exceptions = { [location]: ['a'] };
 
           expect(() => {
             s.setRuleset({ rules: {}, functions: {}, exceptions });
@@ -296,7 +295,7 @@ describe('spectral', () => {
         ['c:/one.yaml#/toto', 'c:/one.yaml#/toto'],
         ['c:\\one.yaml#/toto', 'c:/one.yaml#/toto'],
       ])('normalizes absolute locations (location: "%s")', (location, expected) => {
-        const exceptions = buildRulesetExceptionCollectionFrom(location);
+        const exceptions = { [location]: ['a'] };
 
         s.setRuleset({ rules: {}, functions: {}, exceptions });
 
diff --git a/src/rulesets/asyncapi/__tests__/__helpers__/createWithRules.ts b/src/rulesets/asyncapi/__tests__/__helpers__/createWithRules.ts
new file mode 100644
index 00000000..eae89722
--- /dev/null
+++ b/src/rulesets/asyncapi/__tests__/__helpers__/createWithRules.ts
@@ -0,0 +1,32 @@
+import { STATIC_ASSETS } from '../../../../assets';
+import { empty } from '../../../../utils';
+import { Spectral } from '../../../../spectral';
+import { isAsyncApiv2 } from '../../../../formats';
+import * as ruleset from '../../index.json';
+
+export async function createWithRules(rules: (keyof typeof ruleset['rules'])[]): Promise<Spectral> {
+  try {
+    Object.assign(STATIC_ASSETS, await import('../../../../../rulesets/assets/assets.asyncapi.json'), {
+      'my-ruleset': JSON.stringify({
+        extends: [['spectral:asyncapi', 'off']],
+        rules: rules.reduce((obj, name) => {
+          obj[name] = true;
+          return obj;
+        }, {}),
+      }),
+    });
+
+    const s = new Spectral();
+    s.registerFormat('asyncapi2', isAsyncApiv2);
+
+    await s.loadRuleset('my-ruleset');
+
+    for (const rule of rules) {
+      expect(s.rules[rule].severity).not.toEqual(-1);
+    }
+
+    return s;
+  } finally {
+    empty(STATIC_ASSETS);
+  }
+}
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-empty-parameter.ts b/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-empty-parameter.ts
index 7748cf3f..fc4a6bd6 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-empty-parameter.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-empty-parameter.ts
@@ -1,16 +1,16 @@
 import { cloneDeep } from 'lodash';
 
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
 import { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-channel-no-empty-parameter';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
+    s = await createWithRules([ruleName]);
   });
 
   const doc: any = {
@@ -38,7 +38,7 @@ describe(`Rule '${ruleName}'`, () => {
         code: ruleName,
         message: 'Channel path should not have empty parameter substitution pattern.',
         path: ['channels', 'users/{}/signedOut'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-query-nor-fragment.ts b/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-query-nor-fragment.ts
index 7fb084ec..5e6528f5 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-query-nor-fragment.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-query-nor-fragment.ts
@@ -1,25 +1,24 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
 import { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-channel-no-query-nor-fragment';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {},
+      },
+    };
   });
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {},
-    },
-  };
-
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
 
@@ -27,35 +26,31 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if channels.{channel} contains a query delimiter', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.channels['users/{userId}/signedOut?byMistake={didFatFingerTheSignOutButton}'] = {};
+    doc.channels['users/{userId}/signedOut?byMistake={didFatFingerTheSignOutButton}'] = {};
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Channel path should not include a query (`?`) or a fragment (`#`) delimiter.',
         path: ['channels', 'users/{userId}/signedOut?byMistake={didFatFingerTheSignOutButton}'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
 
   test('return result if channels.{channel} contains a fragment delimiter', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.channels['users/{userId}/signedOut#onPurpose'] = {};
+    doc.channels['users/{userId}/signedOut#onPurpose'] = {};
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Channel path should not include a query (`?`) or a fragment (`#`) delimiter.',
         path: ['channels', 'users/{userId}/signedOut#onPurpose'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-trailing-slash.ts b/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-trailing-slash.ts
index 6125e7ee..2b0ffb57 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-trailing-slash.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-channel-no-trailing-slash.ts
@@ -1,25 +1,24 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { DiagnosticSeverity } from '@stoplight/types';
+import { createWithRules } from './__helpers__/createWithRules';
 
 const ruleName = 'asyncapi-channel-no-trailing-slash';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {},
+      },
+    };
   });
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {},
-    },
-  };
-
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
 
@@ -27,18 +26,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if channels.{channel} ends with a trailing slash', async () => {
-    const clone = cloneDeep(doc);
+    doc.channels['users/{userId}/signedOut/'] = {};
 
-    clone.channels['users/{userId}/signedOut/'] = {};
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Channel path should not end with a slash.',
         path: ['channels', 'users/{userId}/signedOut/'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-headers-schema-type-object.ts b/src/rulesets/asyncapi/__tests__/asyncapi-headers-schema-type-object.ts
index 2ae5a824..092be4f2 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-headers-schema-type-object.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-headers-schema-type-object.ts
@@ -1,50 +1,51 @@
 import { cloneDeep } from 'lodash';
 
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { DiagnosticSeverity } from '@stoplight/types';
+import { createWithRules } from './__helpers__/createWithRules';
 
 const ruleName = 'asyncapi-headers-schema-type-object';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const headersBearer: any = {
-    headers: {
-      type: 'object',
-      properties: {
-        'some-header': {
-          type: 'string',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    const headersBearer = {
+      headers: {
+        type: 'object',
+        properties: {
+          'some-header': {
+            type: 'string',
+          },
         },
       },
-    },
-  };
-
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {
-        publish: {
-          message: cloneDeep(headersBearer),
+    };
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {
+          publish: {
+            message: cloneDeep(headersBearer),
+          },
+          subscribe: {
+            message: cloneDeep(headersBearer),
+          },
         },
-        subscribe: {
-          message: cloneDeep(headersBearer),
-        },
-      },
-    },
-    components: {
-      messageTraits: {
-        aTrait: cloneDeep(headersBearer),
       },
-      messages: {
-        aMessage: cloneDeep(headersBearer),
+      components: {
+        messageTraits: {
+          aTrait: cloneDeep(headersBearer),
+        },
+        messages: {
+          aMessage: cloneDeep(headersBearer),
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -53,11 +54,9 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if components.messages.{message}.headers is not of type "object"', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.components.messages.aMessage.headers = { type: 'integer' };
+    doc.components.messages.aMessage.headers = { type: 'integer' };
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
@@ -65,24 +64,22 @@ describe(`Rule '${ruleName}'`, () => {
         message:
           'Headers schema type should be `object` (`type` property should be equal to one of the allowed values: `object`. Did you mean `object`?).',
         path: ['components', 'messages', 'aMessage', 'headers', 'type'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
 
   test('return result if components.messages.{message}.headers lacks "type" property', async () => {
-    const clone = cloneDeep(doc);
+    doc.components.messages.aMessage.headers = { const: 'Hello World!' };
 
-    clone.components.messages.aMessage.headers = { const: 'Hello World!' };
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Headers schema type should be `object` (`headers` property should have required property `type`).',
         path: ['components', 'messages', 'aMessage', 'headers'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
@@ -100,24 +97,22 @@ describe(`Rule '${ruleName}'`, () => {
         message:
           'Headers schema type should be `object` (`type` property should be equal to one of the allowed values: `object`. Did you mean `object`?).',
         path: ['components', 'messageTraits', 'aTrait', 'headers', 'type'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
 
   test('return result if components.messageTraits.{trait}.headers lacks "type" property', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.components.messageTraits.aTrait.headers = { const: 'Hello World!' };
+    doc.components.messageTraits.aTrait.headers = { const: 'Hello World!' };
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Headers schema type should be `object` (`headers` property should have required property `type`).',
         path: ['components', 'messageTraits', 'aTrait', 'headers'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
@@ -125,18 +120,16 @@ describe(`Rule '${ruleName}'`, () => {
   test.each(['publish', 'subscribe'])(
     'return result if channels.{channel}.%s.message.headers lacks "type" property',
     async (property: string) => {
-      const clone = cloneDeep(doc);
-
-      clone.channels['users/{userId}/signedUp'][property].message.headers = { const: 'Hello World!' };
+      doc.channels['users/{userId}/signedUp'][property].message.headers = { const: 'Hello World!' };
 
-      const results = await s.run(clone, { ignoreUnknownFormat: false });
+      const results = await s.run(doc, { ignoreUnknownFormat: false });
 
       expect(results).toEqual([
         expect.objectContaining({
           code: ruleName,
           message: 'Headers schema type should be `object` (`headers` property should have required property `type`).',
           path: ['channels', 'users/{userId}/signedUp', property, 'message', 'headers'],
-          severity: rule.severity,
+          severity: DiagnosticSeverity.Error,
         }),
       ]);
     },
@@ -145,11 +138,9 @@ describe(`Rule '${ruleName}'`, () => {
   test.each(['publish', 'subscribe'])(
     'return result if channels.{channel}.%s.message.headers is not of type "object"',
     async (property: string) => {
-      const clone = cloneDeep(doc);
-
-      clone.channels['users/{userId}/signedUp'][property].message.headers = { type: 'integer' };
+      doc.channels['users/{userId}/signedUp'][property].message.headers = { type: 'integer' };
 
-      const results = await s.run(clone, { ignoreUnknownFormat: false });
+      const results = await s.run(doc, { ignoreUnknownFormat: false });
 
       expect(results).toEqual([
         expect.objectContaining({
@@ -157,7 +148,7 @@ describe(`Rule '${ruleName}'`, () => {
           message:
             'Headers schema type should be `object` (`type` property should be equal to one of the allowed values: `object`. Did you mean `object`?).',
           path: ['channels', 'users/{userId}/signedUp', property, 'message', 'headers', 'type'],
-          severity: rule.severity,
+          severity: DiagnosticSeverity.Error,
         }),
       ]);
     },
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-info-contact-properties.ts b/src/rulesets/asyncapi/__tests__/asyncapi-info-contact-properties.ts
index 536e087c..c0f6213d 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-info-contact-properties.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-info-contact-properties.ts
@@ -1,28 +1,27 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-info-contact-properties';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    info: {
-      contact: {
-        name: 'stoplight',
-        url: 'stoplight.io',
-        email: 'support@stoplight.io',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      info: {
+        contact: {
+          name: 'stoplight',
+          url: 'stoplight.io',
+          email: 'support@stoplight.io',
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -31,18 +30,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test.each(['name', 'url', 'email'])('return result if contact.%s property is missing', async (property: string) => {
-    const clone = cloneDeep(doc);
-
-    delete clone.info.contact[property];
+    delete doc.info.contact[property];
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Contact object should have `name`, `url` and `email`.',
         path: ['info', 'contact'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-info-contact.ts b/src/rulesets/asyncapi/__tests__/asyncapi-info-contact.ts
index bf05e52d..6e9a610e 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-info-contact.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-info-contact.ts
@@ -1,28 +1,27 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-info-contact';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    info: {
-      contact: {
-        name: 'stoplight',
-        url: 'stoplight.io',
-        email: 'support@stoplight.io',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      info: {
+        contact: {
+          name: 'stoplight',
+          url: 'stoplight.io',
+          email: 'support@stoplight.io',
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -31,18 +30,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if contact property is missing', async () => {
-    const clone = cloneDeep(doc);
-
-    delete clone.info.contact;
+    delete doc.info.contact;
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Info object should contain `contact` object.',
         path: ['info'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-info-description.ts b/src/rulesets/asyncapi/__tests__/asyncapi-info-description.ts
index b34322e4..a83ebeda 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-info-description.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-info-description.ts
@@ -1,25 +1,24 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types/';
 
 const ruleName = 'asyncapi-info-description';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      info: {
+        description: 'Very descriptive list of self explaining consecutive characters.',
+      },
+    };
   });
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    info: {
-      description: 'Very descriptive list of self explaining consecutive characters.',
-    },
-  };
-
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
 
@@ -27,18 +26,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if description property is missing', async () => {
-    const clone = cloneDeep(doc);
+    delete doc.info.description;
 
-    delete clone.info.description;
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'AsyncAPI object info `description` must be present and non-empty string.',
         path: ['info'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-info-license-url.ts b/src/rulesets/asyncapi/__tests__/asyncapi-info-license-url.ts
index bf251066..b1ee2c0c 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-info-license-url.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-info-license-url.ts
@@ -1,26 +1,25 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
 import { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-info-license-url';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    info: {
-      license: {
-        url: 'https://github.com/stoplightio/spectral/blob/develop/LICENSE',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      info: {
+        license: {
+          url: 'https://github.com/stoplightio/spectral/blob/develop/LICENSE',
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -29,18 +28,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if url property is missing', async () => {
-    const clone = cloneDeep(doc);
-
-    delete clone.info.license.url;
+    delete doc.info.license.url;
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'License object should include `url`.',
         path: ['info', 'license'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-info-license.ts b/src/rulesets/asyncapi/__tests__/asyncapi-info-license.ts
index a447b526..f1dcf674 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-info-license.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-info-license.ts
@@ -1,26 +1,25 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-info-license';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    info: {
-      license: {
-        name: 'MIT',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      info: {
+        license: {
+          name: 'MIT',
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -29,18 +28,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if license property is missing', async () => {
-    const clone = cloneDeep(doc);
-
-    delete clone.info.license;
+    delete doc.info.license;
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'AsyncAPI object should contain `license` object.',
         path: ['info'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-operation-description.ts b/src/rulesets/asyncapi/__tests__/asyncapi-operation-description.ts
index 968801e8..cf448da6 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-operation-description.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-operation-description.ts
@@ -1,31 +1,30 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
 import { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-operation-description';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      one: {
-        publish: {
-          description: 'I do this.',
-        },
-        subscribe: {
-          description: '...and that',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        one: {
+          publish: {
+            description: 'I do this.',
+          },
+          subscribe: {
+            description: '...and that',
+          },
         },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -36,18 +35,16 @@ describe(`Rule '${ruleName}'`, () => {
   test.each(['publish', 'subscribe'])(
     'return result if channels.{channel}.%s.description property is missing',
     async (property: string) => {
-      const clone = cloneDeep(doc);
-
-      delete clone.channels.one[property].description;
+      delete doc.channels.one[property].description;
 
-      const results = await s.run(clone, { ignoreUnknownFormat: false });
+      const results = await s.run(doc, { ignoreUnknownFormat: false });
 
       expect(results).toEqual([
         expect.objectContaining({
           code: ruleName,
           message: 'Operation `description` must be present and non-empty string.',
           path: ['channels', 'one', property],
-          severity: rule.severity,
+          severity: DiagnosticSeverity.Warning,
         }),
       ]);
     },
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-operation-operationId.ts b/src/rulesets/asyncapi/__tests__/asyncapi-operation-operationId.ts
index fafbe31b..90f616ca 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-operation-operationId.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-operation-operationId.ts
@@ -1,31 +1,30 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-operation-operationId';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      one: {
-        publish: {
-          operationId: 'onePubId',
-        },
-        subscribe: {
-          operationId: 'oneSubId',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        one: {
+          publish: {
+            operationId: 'onePubId',
+          },
+          subscribe: {
+            operationId: 'oneSubId',
+          },
         },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -36,18 +35,16 @@ describe(`Rule '${ruleName}'`, () => {
   test.each(['publish', 'subscribe'])(
     'return result if channels.{channel}.%s.operationId property is missing',
     async (property: string) => {
-      const clone = cloneDeep(doc);
-
-      delete clone.channels.one[property].operationId;
+      delete doc.channels.one[property].operationId;
 
-      const results = await s.run(clone, { ignoreUnknownFormat: false });
+      const results = await s.run(doc, { ignoreUnknownFormat: false });
 
       expect(results).toEqual([
         expect.objectContaining({
           code: ruleName,
           message: 'Operation should have an `operationId`.',
           path: ['channels', 'one', property],
-          severity: rule.severity,
+          severity: DiagnosticSeverity.Error,
         }),
       ]);
     },
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-parameter-description.ts b/src/rulesets/asyncapi/__tests__/asyncapi-parameter-description.ts
index e4560b6a..93d6bfef 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-parameter-description.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-parameter-description.ts
@@ -1,37 +1,36 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types/';
 
 const ruleName = 'asyncapi-parameter-description';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+    s = await createWithRules([ruleName]);
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {
-        parameters: {
-          userId: {
-            description: 'The identifier of the user being tracked.',
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {
+          parameters: {
+            userId: {
+              description: 'The identifier of the user being tracked.',
+            },
           },
         },
       },
-    },
-    components: {
-      parameters: {
-        orphanParameter: {
-          description: 'A defined, but orphaned, parameter.',
+      components: {
+        parameters: {
+          orphanParameter: {
+            description: 'A defined, but orphaned, parameter.',
+          },
         },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -40,35 +39,31 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if channels.{channel}.parameters.{parameter} lack a description', async () => {
-    const clone = cloneDeep(doc);
-
-    delete clone.channels['users/{userId}/signedUp'].parameters.userId.description;
+    delete doc.channels['users/{userId}/signedUp'].parameters.userId.description;
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Parameter objects should have a `description`.',
         path: ['channels', 'users/{userId}/signedUp', 'parameters', 'userId'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
 
   test('return result if components.parameters.{parameter} lack a description', async () => {
-    const clone = cloneDeep(doc);
+    delete doc.components.parameters.orphanParameter.description;
 
-    delete clone.components.parameters.orphanParameter.description;
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Parameter objects should have a `description`.',
         path: ['components', 'parameters', 'orphanParameter'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-payload-default.ts b/src/rulesets/asyncapi/__tests__/asyncapi-payload-default.ts
index 0ddef64e..0a6fcc3b 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-payload-default.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-payload-default.ts
@@ -1,58 +1,59 @@
 import { cloneDeep } from 'lodash';
 
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-payload-default';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+    s = await createWithRules([ruleName]);
 
-  const payload = {
-    type: 'object',
-    properties: {
-      value: {
-        type: 'integer',
+    const payload = {
+      type: 'object',
+      properties: {
+        value: {
+          type: 'integer',
+        },
       },
-    },
-    required: ['value'],
-    default: { value: 17 },
-  };
-
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {
-        publish: {
-          message: {
-            payload: cloneDeep(payload),
+      required: ['value'],
+      default: { value: 17 },
+    };
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {
+          publish: {
+            message: {
+              payload: cloneDeep(payload),
+            },
           },
-        },
-        subscribe: {
-          message: {
-            payload: cloneDeep(payload),
+          subscribe: {
+            message: {
+              payload: cloneDeep(payload),
+            },
           },
         },
       },
-    },
-    components: {
-      messageTraits: {
-        aTrait: {
-          payload: cloneDeep(payload),
+      components: {
+        messageTraits: {
+          aTrait: {
+            payload: cloneDeep(payload),
+          },
         },
-      },
-      messages: {
-        aMessage: {
-          payload: cloneDeep(payload),
+        messages: {
+          aMessage: {
+            payload: cloneDeep(payload),
+          },
         },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -61,35 +62,31 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if components.messages.{message}.payload.default is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
+    doc.components.messages.aMessage.payload.default = { seventeen: 17 };
 
-    clone.components.messages.aMessage.payload.default = { seventeen: 17 };
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`default` property should have required property `value`',
         path: ['components', 'messages', 'aMessage', 'payload', 'default'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
 
   test('return result if components.messageTraits.{trait}.payload.default is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.components.messageTraits.aTrait.payload.default = { seventeen: 17 };
+    doc.components.messageTraits.aTrait.payload.default = { seventeen: 17 };
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`default` property should have required property `value`',
         path: ['components', 'messageTraits', 'aTrait', 'payload', 'default'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
@@ -97,18 +94,16 @@ describe(`Rule '${ruleName}'`, () => {
   test.each(['publish', 'subscribe'])(
     'return result if channels.{channel}.%s.message.payload.default is not valid against the schema it decorates',
     async (property: string) => {
-      const clone = cloneDeep(doc);
-
-      clone.channels['users/{userId}/signedUp'][property].message.payload.default = { seventeen: 17 };
+      doc.channels['users/{userId}/signedUp'][property].message.payload.default = { seventeen: 17 };
 
-      const results = await s.run(clone, { ignoreUnknownFormat: false });
+      const results = await s.run(doc, { ignoreUnknownFormat: false });
 
       expect(results).toEqual([
         expect.objectContaining({
           code: ruleName,
           message: '`default` property should have required property `value`',
           path: ['channels', 'users/{userId}/signedUp', property, 'message', 'payload', 'default'],
-          severity: rule.severity,
+          severity: DiagnosticSeverity.Error,
         }),
       ]);
     },
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-payload-examples.ts b/src/rulesets/asyncapi/__tests__/asyncapi-payload-examples.ts
index 0a55b8a6..53ff29f6 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-payload-examples.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-payload-examples.ts
@@ -1,58 +1,59 @@
 import { cloneDeep } from 'lodash';
 
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { DiagnosticSeverity } from '@stoplight/types';
+import { createWithRules } from './__helpers__/createWithRules';
 
 const ruleName = 'asyncapi-payload-examples';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+    s = await createWithRules([ruleName]);
 
-  const payload = {
-    type: 'object',
-    properties: {
-      value: {
-        type: 'integer',
+    const payload = {
+      type: 'object',
+      properties: {
+        value: {
+          type: 'integer',
+        },
       },
-    },
-    required: ['value'],
-    examples: [{ value: 17 }, { value: 18 }],
-  };
-
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {
-        publish: {
-          message: {
-            payload: cloneDeep(payload),
+      required: ['value'],
+      examples: [{ value: 17 }, { value: 18 }],
+    };
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {
+          publish: {
+            message: {
+              payload: cloneDeep(payload),
+            },
           },
-        },
-        subscribe: {
-          message: {
-            payload: cloneDeep(payload),
+          subscribe: {
+            message: {
+              payload: cloneDeep(payload),
+            },
           },
         },
       },
-    },
-    components: {
-      messageTraits: {
-        aTrait: {
-          payload: cloneDeep(payload),
+      components: {
+        messageTraits: {
+          aTrait: {
+            payload: cloneDeep(payload),
+          },
         },
-      },
-      messages: {
-        aMessage: {
-          payload: cloneDeep(payload),
+        messages: {
+          aMessage: {
+            payload: cloneDeep(payload),
+          },
         },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -61,35 +62,31 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if components.messages.{message}.payload.examples.{position} is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
+    doc.components.messages.aMessage.payload.examples[1] = { seventeen: 17 };
 
-    clone.components.messages.aMessage.payload.examples[1] = { seventeen: 17 };
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`1` property should have required property `value`',
         path: ['components', 'messages', 'aMessage', 'payload', 'examples', '1'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
 
   test('return result if components.messageTraits.{trait}.payload.examples.{position} is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.components.messageTraits.aTrait.payload.examples[1] = { seventeen: 17 };
+    doc.components.messageTraits.aTrait.payload.examples[1] = { seventeen: 17 };
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`1` property should have required property `value`',
         path: ['components', 'messageTraits', 'aTrait', 'payload', 'examples', '1'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
@@ -97,18 +94,16 @@ describe(`Rule '${ruleName}'`, () => {
   test.each(['publish', 'subscribe'])(
     'return result if channels.{channel}.%s.message.payload.examples.{position} is not valid against the schema it decorates',
     async (property: string) => {
-      const clone = cloneDeep(doc);
-
-      clone.channels['users/{userId}/signedUp'][property].message.payload.examples[1] = { seventeen: 17 };
+      doc.channels['users/{userId}/signedUp'][property].message.payload.examples[1] = { seventeen: 17 };
 
-      const results = await s.run(clone, { ignoreUnknownFormat: false });
+      const results = await s.run(doc, { ignoreUnknownFormat: false });
 
       expect(results).toEqual([
         expect.objectContaining({
           code: ruleName,
           message: '`1` property should have required property `value`',
           path: ['channels', 'users/{userId}/signedUp', property, 'message', 'payload', 'examples', '1'],
-          severity: rule.severity,
+          severity: DiagnosticSeverity.Error,
         }),
       ]);
     },
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-payload-unsupported-schemaFormat.ts b/src/rulesets/asyncapi/__tests__/asyncapi-payload-unsupported-schemaFormat.ts
index 6d8873bb..4734f82d 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-payload-unsupported-schemaFormat.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-payload-unsupported-schemaFormat.ts
@@ -1,39 +1,38 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-payload-unsupported-schemaFormat';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {
-        publish: {
-          message: {},
-        },
-        subscribe: {
-          message: {},
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {
+          publish: {
+            message: {},
+          },
+          subscribe: {
+            message: {},
+          },
         },
       },
-    },
-    components: {
-      messageTraits: {
-        aTrait: {},
-      },
-      messages: {
-        aMessage: {},
+      components: {
+        messageTraits: {
+          aTrait: {},
+        },
+        messages: {
+          aMessage: {},
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -42,35 +41,31 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if components.messages.{message}.schemaFormat is set to a non supported value', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.components.messages.aMessage.schemaFormat = 'application/nope';
+    doc.components.messages.aMessage.schemaFormat = 'application/nope';
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Message schema validation is only supported with default unspecified `schemaFormat`.',
         path: ['components', 'messages', 'aMessage', 'schemaFormat'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Information,
       }),
     ]);
   });
 
   test('return result if components.messageTraits.{trait}.schemaFormat is set to a non supported value', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.components.messageTraits.aTrait.schemaFormat = 'application/nope';
+    doc.components.messageTraits.aTrait.schemaFormat = 'application/nope';
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Message schema validation is only supported with default unspecified `schemaFormat`.',
         path: ['components', 'messageTraits', 'aTrait', 'schemaFormat'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Information,
       }),
     ]);
   });
@@ -78,18 +73,16 @@ describe(`Rule '${ruleName}'`, () => {
   test.each(['publish', 'subscribe'])(
     'return result if channels.{channel}.%s.message.schemaFormat is set to a non supported value',
     async (property: string) => {
-      const clone = cloneDeep(doc);
-
-      clone.channels['users/{userId}/signedUp'][property].message.schemaFormat = 'application/nope';
+      doc.channels['users/{userId}/signedUp'][property].message.schemaFormat = 'application/nope';
 
-      const results = await s.run(clone, { ignoreUnknownFormat: false });
+      const results = await s.run(doc, { ignoreUnknownFormat: false });
 
       expect(results).toEqual([
         expect.objectContaining({
           code: ruleName,
           message: 'Message schema validation is only supported with default unspecified `schemaFormat`.',
           path: ['channels', 'users/{userId}/signedUp', property, 'message', 'schemaFormat'],
-          severity: rule.severity,
+          severity: DiagnosticSeverity.Information,
         }),
       ]);
     },
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-payload.ts b/src/rulesets/asyncapi/__tests__/asyncapi-payload.ts
index 77955dcb..a836b8eb 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-payload.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-payload.ts
@@ -1,57 +1,57 @@
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 import { cloneDeep } from 'lodash';
 
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
-
 const ruleName = 'asyncapi-payload';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+    s = await createWithRules([ruleName]);
 
-  const payload = {
-    type: 'object',
-    properties: {
-      value: {
-        type: 'integer',
+    const payload = {
+      type: 'object',
+      properties: {
+        value: {
+          type: 'integer',
+        },
       },
-    },
-    required: ['value'],
-  };
-
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {
-        publish: {
-          message: {
-            payload: cloneDeep(payload),
+      required: ['value'],
+    };
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {
+          publish: {
+            message: {
+              payload: cloneDeep(payload),
+            },
           },
-        },
-        subscribe: {
-          message: {
-            payload: cloneDeep(payload),
+          subscribe: {
+            message: {
+              payload: cloneDeep(payload),
+            },
           },
         },
       },
-    },
-    components: {
-      messageTraits: {
-        aTrait: {
-          payload: cloneDeep(payload),
+      components: {
+        messageTraits: {
+          aTrait: {
+            payload: cloneDeep(payload),
+          },
         },
-      },
-      messages: {
-        aMessage: {
-          payload: cloneDeep(payload),
+        messages: {
+          aMessage: {
+            payload: cloneDeep(payload),
+          },
         },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -60,35 +60,31 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if components.messages.{message}.payload is not valid against the AsyncApi2 schema object', async () => {
-    const clone = cloneDeep(doc);
+    doc.components.messages.aMessage.payload.deprecated = 17;
 
-    clone.components.messages.aMessage.payload.deprecated = 17;
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`deprecated` property type should be boolean',
         path: ['components', 'messages', 'aMessage', 'payload', 'deprecated'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
 
   test('return result if components.messageTraits.{trait}.payload is not valid against the AsyncApi2 schema object', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.components.messageTraits.aTrait.payload.deprecated = 17;
+    doc.components.messageTraits.aTrait.payload.deprecated = 17;
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`deprecated` property type should be boolean',
         path: ['components', 'messageTraits', 'aTrait', 'payload', 'deprecated'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
@@ -96,18 +92,16 @@ describe(`Rule '${ruleName}'`, () => {
   test.each(['publish', 'subscribe'])(
     'return result if channels.{channel}.%s.message.payload is not valid against the AsyncApi2 schema object',
     async (property: string) => {
-      const clone = cloneDeep(doc);
-
-      clone.channels['users/{userId}/signedUp'][property].message.payload.deprecated = 17;
+      doc.channels['users/{userId}/signedUp'][property].message.payload.deprecated = 17;
 
-      const results = await s.run(clone, { ignoreUnknownFormat: false });
+      const results = await s.run(doc, { ignoreUnknownFormat: false });
 
       expect(results).toEqual([
         expect.objectContaining({
           code: ruleName,
           message: '`deprecated` property type should be boolean',
           path: ['channels', 'users/{userId}/signedUp', property, 'message', 'payload', 'deprecated'],
-          severity: rule.severity,
+          severity: DiagnosticSeverity.Error,
         }),
       ]);
     },
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-schema-default.ts b/src/rulesets/asyncapi/__tests__/asyncapi-schema-default.ts
index 3b0ba591..7ee40651 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-schema-default.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-schema-default.ts
@@ -1,46 +1,45 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { DiagnosticSeverity } from '@stoplight/types';
+import { createWithRules } from './__helpers__/createWithRules';
 
 const ruleName = 'asyncapi-schema-default';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {
+          parameters: {
+            userId: {
+              schema: {
+                default: 17,
+              },
+            },
+          },
+        },
+      },
+      components: {
         parameters: {
-          userId: {
+          orphanParameter: {
             schema: {
               default: 17,
             },
           },
         },
-      },
-    },
-    components: {
-      parameters: {
-        orphanParameter: {
-          schema: {
+        schemas: {
+          aSchema: {
             default: 17,
           },
         },
       },
-      schemas: {
-        aSchema: {
-          default: 17,
-        },
-      },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -49,51 +48,45 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if components.schemas.{schema}.default is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
+    doc.components.schemas.aSchema.type = 'string';
 
-    clone.components.schemas.aSchema.type = 'string';
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`default` property type should be string',
         path: ['components', 'schemas', 'aSchema', 'default'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
 
   test('return result if components.parameters.{parameter}.schema.default is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
+    doc.components.parameters.orphanParameter.schema.type = 'string';
 
-    clone.components.parameters.orphanParameter.schema.type = 'string';
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`default` property type should be string',
         path: ['components', 'parameters', 'orphanParameter', 'schema', 'default'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
 
   test('return result if channels.{channel}.parameters.{parameter}.schema.default is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.channels['users/{userId}/signedUp'].parameters.userId.schema.type = 'string';
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    doc.channels['users/{userId}/signedUp'].parameters.userId.schema.type = 'string';
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`default` property type should be string',
         path: ['channels', 'users/{userId}/signedUp', 'parameters', 'userId', 'schema', 'default'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-schema-examples.ts b/src/rulesets/asyncapi/__tests__/asyncapi-schema-examples.ts
index 322b32dd..12f75772 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-schema-examples.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-schema-examples.ts
@@ -1,46 +1,45 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-schema-examples';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/{userId}/signedUp': {
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/{userId}/signedUp': {
+          parameters: {
+            userId: {
+              schema: {
+                examples: [17, 'one', 13],
+              },
+            },
+          },
+        },
+      },
+      components: {
         parameters: {
-          userId: {
+          orphanParameter: {
             schema: {
               examples: [17, 'one', 13],
             },
           },
         },
-      },
-    },
-    components: {
-      parameters: {
-        orphanParameter: {
-          schema: {
+        schemas: {
+          aSchema: {
             examples: [17, 'one', 13],
           },
         },
       },
-      schemas: {
-        aSchema: {
-          examples: [17, 'one', 13],
-        },
-      },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -49,69 +48,63 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if components.schemas.{schema}.examples.{position} is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
+    doc.components.schemas.aSchema.type = 'string';
 
-    clone.components.schemas.aSchema.type = 'string';
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`0` property type should be string',
         path: ['components', 'schemas', 'aSchema', 'examples', '0'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
       expect.objectContaining({
         code: ruleName,
         message: '`2` property type should be string',
         path: ['components', 'schemas', 'aSchema', 'examples', '2'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
 
   test('return result if components.parameters.{parameter}.schema.examples.{position} is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
+    doc.components.parameters.orphanParameter.schema.type = 'string';
 
-    clone.components.parameters.orphanParameter.schema.type = 'string';
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`0` property type should be string',
         path: ['components', 'parameters', 'orphanParameter', 'schema', 'examples', '0'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
       expect.objectContaining({
         code: ruleName,
         message: '`2` property type should be string',
         path: ['components', 'parameters', 'orphanParameter', 'schema', 'examples', '2'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
 
   test('return result if channels.{channel}.parameters.{parameter}.schema.examples.{position} is not valid against the schema it decorates', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.channels['users/{userId}/signedUp'].parameters.userId.schema.type = 'string';
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    doc.channels['users/{userId}/signedUp'].parameters.userId.schema.type = 'string';
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: '`0` property type should be string',
         path: ['channels', 'users/{userId}/signedUp', 'parameters', 'userId', 'schema', 'examples', '0'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
       expect.objectContaining({
         code: ruleName,
         message: '`2` property type should be string',
         path: ['channels', 'users/{userId}/signedUp', 'parameters', 'userId', 'schema', 'examples', '2'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-schema.ts b/src/rulesets/asyncapi/__tests__/asyncapi-schema.ts
index ffc38b7a..8ec8b3f8 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-schema.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-schema.ts
@@ -1,27 +1,26 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
 import { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-schema';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      info: {
+        title: 'Valid AsyncApi document',
+        version: '1.0',
+      },
+      channels: {},
+    };
   });
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    info: {
-      title: 'Valid AsyncApi document',
-      version: '1.0',
-    },
-    channels: {},
-  };
-
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
 
@@ -29,18 +28,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if channels property is missing', async () => {
-    const clone = cloneDeep(doc);
+    delete doc.channels;
 
-    delete clone.channels;
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Object should have required property `channels`',
         path: [],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Error,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-server-no-empty-variable.ts b/src/rulesets/asyncapi/__tests__/asyncapi-server-no-empty-variable.ts
index a1f135de..ff712be4 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-server-no-empty-variable.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-server-no-empty-variable.ts
@@ -1,27 +1,26 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { DiagnosticSeverity } from '@stoplight/types';
+import { createWithRules } from './__helpers__/createWithRules';
 
 const ruleName = 'asyncapi-server-no-empty-variable';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    servers: {
-      production: {
-        url: '{sub}.stoplight.io',
-        protocol: 'https',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      servers: {
+        production: {
+          url: '{sub}.stoplight.io',
+          protocol: 'https',
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -30,18 +29,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if {server}.url property contains empty variable substitution pattern', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.servers.production.url = '{}.stoplight.io';
+    doc.servers.production.url = '{}.stoplight.io';
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Server URL should not have empty variable substitution pattern.',
         path: ['servers', 'production', 'url'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-server-no-trailing-slash.ts b/src/rulesets/asyncapi/__tests__/asyncapi-server-no-trailing-slash.ts
index e3b03109..46c0b81a 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-server-no-trailing-slash.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-server-no-trailing-slash.ts
@@ -1,27 +1,26 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { DiagnosticSeverity } from '@stoplight/types';
+import { createWithRules } from './__helpers__/createWithRules';
 
 const ruleName = 'asyncapi-server-no-trailing-slash';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    servers: {
-      production: {
-        url: 'stoplight.io',
-        protocol: 'https',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      servers: {
+        production: {
+          url: 'stoplight.io',
+          protocol: 'https',
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -30,18 +29,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if {server}.url property ends with a trailing slash', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.servers.production.url = 'stoplight.io/';
+    doc.servers.production.url = 'stoplight.io/';
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Server URL should not end with a slash.',
         path: ['servers', 'production', 'url'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-server-not-example-com.ts b/src/rulesets/asyncapi/__tests__/asyncapi-server-not-example-com.ts
index 136a7b3f..ee381678 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-server-not-example-com.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-server-not-example-com.ts
@@ -1,27 +1,26 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
 import { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-server-not-example-com';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    servers: {
-      production: {
-        url: 'stoplight.io',
-        protocol: 'https',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      servers: {
+        production: {
+          url: 'stoplight.io',
+          protocol: 'https',
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -30,18 +29,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if {server}.url property is set to `example.com`', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.servers.production.url = 'example.com';
+    doc.servers.production.url = 'example.com';
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Server URL should not point at example.com.',
         path: ['servers', 'production', 'url'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-servers.ts b/src/rulesets/asyncapi/__tests__/asyncapi-servers.ts
index c4748026..fc1f0476 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-servers.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-servers.ts
@@ -1,27 +1,26 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-servers';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
-  beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+  let s: Spectral;
+  let doc: any;
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    servers: {
-      production: {
-        url: 'stoplight.io',
-        protocol: 'https',
+  beforeEach(async () => {
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      servers: {
+        production: {
+          url: 'stoplight.io',
+          protocol: 'https',
+        },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -30,36 +29,32 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if servers property is missing', async () => {
-    const clone = cloneDeep(doc);
+    delete doc.servers;
 
-    delete clone.servers;
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'AsyncAPI object should contain a non empty `servers` object.',
         path: [],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
 
   test('return result if servers property is empty', async () => {
-    const clone = cloneDeep(doc);
+    delete doc.servers.production;
+    expect(doc.servers).toEqual({});
 
-    delete clone.servers.production;
-    expect(clone.servers).toEqual({});
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'AsyncAPI object should contain a non empty `servers` object.',
         path: ['servers'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-tag-description.ts b/src/rulesets/asyncapi/__tests__/asyncapi-tag-description.ts
index 2db2adb4..2edfea47 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-tag-description.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-tag-description.ts
@@ -1,28 +1,27 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-tag-description';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
+    s = await createWithRules([ruleName]);
+
+    doc = {
+      asyncapi: '2.0.0',
+      tags: [
+        {
+          name: 'a tag',
+          description: "I'm a tag.",
+        },
+      ],
+    };
   });
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    tags: [
-      {
-        name: 'a tag',
-        description: "I'm a tag.",
-      },
-    ],
-  };
-
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
 
@@ -30,18 +29,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if description property is missing', async () => {
-    const clone = cloneDeep(doc);
+    delete doc.tags[0].description;
 
-    delete clone.tags[0].description;
-
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Tag object should have a `description`.',
         path: ['tags', '0'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-tags-alphabetical.ts b/src/rulesets/asyncapi/__tests__/asyncapi-tags-alphabetical.ts
index 4b997130..cd945684 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-tags-alphabetical.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-tags-alphabetical.ts
@@ -1,22 +1,21 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { DiagnosticSeverity } from '@stoplight/types';
+import { createWithRules } from './__helpers__/createWithRules';
 
 const ruleName = 'asyncapi-tags-alphabetical';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+    s = await createWithRules([ruleName]);
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    tags: [{ name: 'a tag' }, { name: 'another tag' }],
-  };
+    doc = {
+      asyncapi: '2.0.0',
+      tags: [{ name: 'a tag' }, { name: 'another tag' }],
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -25,18 +24,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if tags are not sorted', async () => {
-    const clone = cloneDeep(doc);
-
-    clone.tags = [{ name: 'wrongly ordered' }, ...clone.tags];
+    doc.tags = [{ name: 'wrongly ordered' }, ...doc.tags];
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'AsyncAPI object should have alphabetical `tags`.',
         path: ['tags'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-tags.ts b/src/rulesets/asyncapi/__tests__/asyncapi-tags.ts
index 9d77920b..bccdfa16 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-tags.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-tags.ts
@@ -1,22 +1,21 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
-import { Spectral } from '../../../spectral';
+import type { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-tags';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+    s = await createWithRules([ruleName]);
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    tags: [{ name: 'one' }, { name: 'another' }],
-  };
+    doc = {
+      asyncapi: '2.0.0',
+      tags: [{ name: 'one' }, { name: 'another' }],
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -25,18 +24,16 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if tags property is missing', async () => {
-    const clone = cloneDeep(doc);
-
-    delete clone.tags;
+    delete doc.tags;
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'AsyncAPI object should have non-empty `tags` array.',
         path: [],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/asyncapi/__tests__/asyncapi-unused-components-schema.ts b/src/rulesets/asyncapi/__tests__/asyncapi-unused-components-schema.ts
index caab3a42..7ef14fed 100644
--- a/src/rulesets/asyncapi/__tests__/asyncapi-unused-components-schema.ts
+++ b/src/rulesets/asyncapi/__tests__/asyncapi-unused-components-schema.ts
@@ -1,39 +1,38 @@
-import { cloneDeep } from 'lodash';
-
-import { buildTestSpectralWithAsyncApiRule } from '../../../../setupTests';
-import { Rule } from '../../../rule';
 import { Spectral } from '../../../spectral';
+import { createWithRules } from './__helpers__/createWithRules';
+import { DiagnosticSeverity } from '@stoplight/types';
 
 const ruleName = 'asyncapi-unused-components-schema';
-let s: Spectral;
-let rule: Rule;
 
 describe(`Rule '${ruleName}'`, () => {
+  let s: Spectral;
+  let doc: any;
+
   beforeEach(async () => {
-    [s, rule] = await buildTestSpectralWithAsyncApiRule(ruleName);
-  });
+    s = await createWithRules([ruleName]);
 
-  const doc: any = {
-    asyncapi: '2.0.0',
-    channels: {
-      'users/signedUp': {
-        subscribe: {
-          message: {
-            payload: {
-              $ref: '#/components/schemas/externallyDefinedUser',
+    doc = {
+      asyncapi: '2.0.0',
+      channels: {
+        'users/signedUp': {
+          subscribe: {
+            message: {
+              payload: {
+                $ref: '#/components/schemas/externallyDefinedUser',
+              },
             },
           },
         },
       },
-    },
-    components: {
-      schemas: {
-        externallyDefinedUser: {
-          type: 'string',
+      components: {
+        schemas: {
+          externallyDefinedUser: {
+            type: 'string',
+          },
         },
       },
-    },
-  };
+    };
+  });
 
   test('validates a correct object', async () => {
     const results = await s.run(doc, { ignoreUnknownFormat: false });
@@ -42,11 +41,9 @@ describe(`Rule '${ruleName}'`, () => {
   });
 
   test('return result if components.schemas contains unreferenced objects', async () => {
-    const clone = cloneDeep(doc);
+    delete doc.channels['users/signedUp'];
 
-    delete clone.channels['users/signedUp'];
-
-    clone.channels['users/signedOut'] = {
+    doc.channels['users/signedOut'] = {
       subscribe: {
         message: {
           payload: {
@@ -56,14 +53,14 @@ describe(`Rule '${ruleName}'`, () => {
       },
     };
 
-    const results = await s.run(clone, { ignoreUnknownFormat: false });
+    const results = await s.run(doc, { ignoreUnknownFormat: false });
 
     expect(results).toEqual([
       expect.objectContaining({
         code: ruleName,
         message: 'Potentially unused components schema has been detected.',
         path: ['components', 'schemas', 'externallyDefinedUser'],
-        severity: rule.severity,
+        severity: DiagnosticSeverity.Warning,
       }),
     ]);
   });
diff --git a/src/rulesets/mergers/__tests__/exceptions.test.ts b/src/rulesets/mergers/__tests__/exceptions.test.ts
index 423b8cb3..df8cb678 100644
--- a/src/rulesets/mergers/__tests__/exceptions.test.ts
+++ b/src/rulesets/mergers/__tests__/exceptions.test.ts
@@ -2,8 +2,6 @@ import { escapeRegExp } from 'lodash';
 import { RulesetExceptionCollection } from '../../../types/ruleset';
 import { mergeExceptions } from '../exceptions';
 
-import { buildRulesetExceptionCollectionFrom } from '../../../../setupTests';
-
 describe('Ruleset exceptions merging', () => {
   describe('when loaded from a ruleset', () => {
     const dummyRulesetUri = './ruleset.yaml';
@@ -80,7 +78,7 @@ describe('Ruleset exceptions merging', () => {
         it.each(invalidLocations)(
           'throws when locations are not valid uris (including fragment): "%s"',
           async location => {
-            const source = buildRulesetExceptionCollectionFrom(location);
+            const source = { [location]: ['a'] };
 
             expect(() => {
               mergeExceptions({}, source, dummyRulesetUri);
@@ -95,7 +93,7 @@ describe('Ruleset exceptions merging', () => {
 
       describe('throws on empty rules array', () => {
         const location = 'one.yaml#/';
-        const source = buildRulesetExceptionCollectionFrom(location, []);
+        const source = { [location]: [] };
 
         expect(() => {
           mergeExceptions({}, source, dummyRulesetUri);
@@ -110,7 +108,7 @@ describe('Ruleset exceptions merging', () => {
 
       describe('throws on empty rule name', () => {
         const location = 'one.yaml#/';
-        const source = buildRulesetExceptionCollectionFrom(location, ['b', '']);
+        const source = { [location]: ['b', ''] };
 
         expect(() => {
           mergeExceptions({}, source, dummyRulesetUri);
@@ -148,12 +146,12 @@ describe('Ruleset exceptions merging', () => {
       it.each(relativeLocations)(
         'combines relative locations with ruleset uri (ruleset: "%s", location: "%s")',
         (rulesetUri, location, expectedLocation) => {
-          const source = buildRulesetExceptionCollectionFrom(location);
+          const source = { [location]: ['a'] };
           const target = {};
 
           mergeExceptions(target, source, rulesetUri);
 
-          const expected = buildRulesetExceptionCollectionFrom(expectedLocation);
+          const expected = { [expectedLocation]: ['a'] };
           expect(target).toEqual(expected);
         },
       );
@@ -179,12 +177,12 @@ describe('Ruleset exceptions merging', () => {
       it.each(absoluteLocations)(
         'normalize absolute locations (ruleset: "%s", location: "%s")',
         (rulesetUri, location, expectedLocation) => {
-          const source = buildRulesetExceptionCollectionFrom(location);
+          const source = { [location]: ['a'] };
           const target = {};
 
           mergeExceptions(target, source, rulesetUri);
 
-          const expected = buildRulesetExceptionCollectionFrom(expectedLocation);
+          const expected = { [expectedLocation]: ['a'] };
           expect(target).toEqual(expected);
         },
       );
diff --git a/src/runner/utils/__tests__/pivotExceptions.test.ts b/src/runner/utils/__tests__/pivotExceptions.test.ts
index c41b294f..f42707f3 100644
--- a/src/runner/utils/__tests__/pivotExceptions.test.ts
+++ b/src/runner/utils/__tests__/pivotExceptions.test.ts
@@ -2,7 +2,6 @@ import { DiagnosticSeverity, Dictionary } from '@stoplight/types';
 import { InvalidUriError } from '../../../rulesets/mergers/exceptions';
 import { ExceptionLocation, pivotExceptions } from '../pivotExceptions';
 
-import { buildRulesetExceptionCollectionFrom } from '../../../../setupTests';
 import { Rule } from '../../../rule';
 
 describe('pivotExceptions', () => {
@@ -56,7 +55,7 @@ describe('pivotExceptions', () => {
   });
 
   it.each([['']])('throws upon detected malformed location (%s)', malformed => {
-    const bad = buildRulesetExceptionCollectionFrom(malformed);
+    const bad = { [malformed]: ['a'] };
 
     expect(() => {
       pivotExceptions(bad, {});