Repository: stoplightio/spectral
Pull request #1135 (2020-05-01 22:24:06)

fix(oas): path-params reports actual endpoint path
Fixes https://github.com/stoplightio/spectral/issues/1130

**Checklist**

- [x] Tests added / updated
- [x] Docs added / updated

**Does this PR introduce a breaking change?**

- [ ] Yes
- [x] No


**Additional context**

Make sure to answer my question before reviewing :sweat_smile: 
https://github.com/stoplightio/spectral/issues/1130#issuecomment-622588402

P0lip: This is the range for `paths` ![image](https://user-images.githubusercontent.com/9273484/81077783-b8615000-8eed-11ea-9f0c-bda48ba0d95d.png)


Patch:
diff --git a/src/rulesets/oas/functions/oasPathParam.ts b/src/rulesets/oas/functions/oasPathParam.ts
index adbd400c..fd3ebf91 100644
--- a/src/rulesets/oas/functions/oasPathParam.ts
+++ b/src/rulesets/oas/functions/oasPathParam.ts
@@ -115,6 +115,7 @@ export const oasPathParam: IFunction = (targetVal, _options, paths, vals) => {
         generateResult(`The paths \`${uniquePaths[normalized]}\` and \`${path}\` are equivalent.`, [
           ...paths.given,
           'paths',
+          path,
         ]),
       );
     } else {


Test patch:
diff --git a/src/rulesets/oas/functions/__tests__/oasOp2xxResponse.test.ts b/src/rulesets/oas/functions/__tests__/oasOp2xxResponse.test.ts
index 1523672a..232fda4a 100644
--- a/src/rulesets/oas/functions/__tests__/oasOp2xxResponse.test.ts
+++ b/src/rulesets/oas/functions/__tests__/oasOp2xxResponse.test.ts
@@ -4,13 +4,17 @@ import { rules } from '../../index.json';
 import oasOp2xxResponse from '../oasOp2xxResponse';
 
 describe('oasOp2xxResponse', () => {
-  const s = new Spectral();
-  s.setFunctions({ oasOp2xxResponse });
-  s.setRules({
-    'operation-2xx-response': Object.assign(rules['operation-2xx-response'], {
-      recommended: true,
-      type: RuleType[rules['operation-2xx-response'].type],
-    }),
+  let s: Spectral;
+
+  beforeEach(() => {
+    s = new Spectral();
+    s.setFunctions({ oasOp2xxResponse });
+    s.setRules({
+      'operation-2xx-response': Object.assign(rules['operation-2xx-response'], {
+        recommended: true,
+        type: RuleType[rules['operation-2xx-response'].type],
+      }),
+    });
   });
 
   test('validate a correct object', async () => {
diff --git a/src/rulesets/oas/functions/__tests__/oasOpFormDataConsumeCheck.test.ts b/src/rulesets/oas/functions/__tests__/oasOpFormDataConsumeCheck.test.ts
index 38da524b..8066f0d2 100644
--- a/src/rulesets/oas/functions/__tests__/oasOpFormDataConsumeCheck.test.ts
+++ b/src/rulesets/oas/functions/__tests__/oasOpFormDataConsumeCheck.test.ts
@@ -4,14 +4,18 @@ import { rules } from '../../index.json';
 import oasOpFormDataConsumeCheck from '../oasOpFormDataConsumeCheck';
 
 describe('oasOpFormDataConsumeCheck', () => {
-  const s = new Spectral();
-  s.registerFormat('oas2', () => true);
-  s.setFunctions({ oasOpFormDataConsumeCheck });
-  s.setRules({
-    'oas2-operation-formData-consume-check': Object.assign(rules['oas2-operation-formData-consume-check'], {
-      recommended: true,
-      type: RuleType[rules['oas2-operation-formData-consume-check'].type],
-    }),
+  let s: Spectral;
+
+  beforeEach(() => {
+    s = new Spectral();
+    s.registerFormat('oas2', () => true);
+    s.setFunctions({ oasOpFormDataConsumeCheck });
+    s.setRules({
+      'oas2-operation-formData-consume-check': Object.assign(rules['oas2-operation-formData-consume-check'], {
+        recommended: true,
+        type: RuleType[rules['oas2-operation-formData-consume-check'].type],
+      }),
+    });
   });
 
   test('validate a correct object', async () => {
diff --git a/src/rulesets/oas/functions/__tests__/oasOpIdUnique.test.ts b/src/rulesets/oas/functions/__tests__/oasOpIdUnique.test.ts
index 814f5878..d2adde7d 100644
--- a/src/rulesets/oas/functions/__tests__/oasOpIdUnique.test.ts
+++ b/src/rulesets/oas/functions/__tests__/oasOpIdUnique.test.ts
@@ -5,14 +5,17 @@ import { rules } from '../../index.json';
 import oasOpIdUnique from '../oasOpIdUnique';
 
 describe('oasOpIdUnique', () => {
-  const s = new Spectral();
+  let s: Spectral;
 
-  s.setFunctions({ oasOpIdUnique });
-  s.setRules({
-    'operation-operationId-unique': Object.assign(rules['operation-operationId-unique'], {
-      recommended: true,
-      type: RuleType[rules['operation-operationId-unique'].type],
-    }),
+  beforeEach(() => {
+    s = new Spectral();
+    s.setFunctions({ oasOpIdUnique });
+    s.setRules({
+      'operation-operationId-unique': Object.assign(rules['operation-operationId-unique'], {
+        recommended: true,
+        type: RuleType[rules['operation-operationId-unique'].type],
+      }),
+    });
   });
 
   test('validate a correct object', async () => {
diff --git a/src/rulesets/oas/functions/__tests__/oasOpParams.test.ts b/src/rulesets/oas/functions/__tests__/oasOpParams.test.ts
index 1fe2674e..cc509295 100644
--- a/src/rulesets/oas/functions/__tests__/oasOpParams.test.ts
+++ b/src/rulesets/oas/functions/__tests__/oasOpParams.test.ts
@@ -4,13 +4,17 @@ import { rules } from '../../index.json';
 import oasOpParams from '../oasOpParams';
 
 describe('oasOpParams', () => {
-  const s = new Spectral();
-  s.setFunctions({ oasOpParams });
-  s.setRules({
-    'operation-parameters': Object.assign(rules['operation-parameters'], {
-      recommended: true,
-      type: RuleType[rules['operation-parameters'].type],
-    }),
+  let s: Spectral;
+
+  beforeEach(() => {
+    s = new Spectral();
+    s.setFunctions({ oasOpParams });
+    s.setRules({
+      'operation-parameters': Object.assign(rules['operation-parameters'], {
+        recommended: true,
+        type: RuleType[rules['operation-parameters'].type],
+      }),
+    });
   });
 
   test('No error if no params', async () => {
diff --git a/src/rulesets/oas/functions/__tests__/oasOpSecurityDefined.test.ts b/src/rulesets/oas/functions/__tests__/oasOpSecurityDefined.test.ts
index d1071209..26367295 100644
--- a/src/rulesets/oas/functions/__tests__/oasOpSecurityDefined.test.ts
+++ b/src/rulesets/oas/functions/__tests__/oasOpSecurityDefined.test.ts
@@ -5,14 +5,18 @@ import oasOpSecurityDefined from '../oasOpSecurityDefined';
 
 describe('oasOpSecurityDefined', () => {
   describe('oas2', () => {
-    const s = new Spectral();
-    s.registerFormat('oas2', () => true);
-    s.setFunctions({ oasOpSecurityDefined });
-    s.setRules({
-      'oas2-operation-security-defined': Object.assign(oasRules['oas2-operation-security-defined'], {
-        recommended: true,
-        type: RuleType[oasRules['oas2-operation-security-defined'].type],
-      }),
+    let s: Spectral;
+
+    beforeEach(() => {
+      s = new Spectral();
+      s.registerFormat('oas2', () => true);
+      s.setFunctions({ oasOpSecurityDefined });
+      s.setRules({
+        'oas2-operation-security-defined': Object.assign(oasRules['oas2-operation-security-defined'], {
+          recommended: true,
+          type: RuleType[oasRules['oas2-operation-security-defined'].type],
+        }),
+      });
     });
 
     test('validate a correct object (just in body)', async () => {
diff --git a/src/rulesets/oas/functions/__tests__/oasPathParam.test.ts b/src/rulesets/oas/functions/__tests__/oasPathParam.test.ts
index 931f5f00..53261b10 100644
--- a/src/rulesets/oas/functions/__tests__/oasPathParam.test.ts
+++ b/src/rulesets/oas/functions/__tests__/oasPathParam.test.ts
@@ -1,16 +1,20 @@
 import { DiagnosticSeverity } from '@stoplight/types';
-import { RuleType, Spectral } from '../../../../index';
+import { Document, Parsers, RuleType, Spectral } from '../../../../index';
 import { rules } from '../../index.json';
 import oasPathParam from '../oasPathParam';
 
 describe('oasPathParam', () => {
-  const s = new Spectral();
-  s.setFunctions({ oasPathParam });
-  s.setRules({
-    'path-params': Object.assign(rules['path-params'], {
-      recommended: true,
-      type: RuleType[rules['path-params'].type],
-    }),
+  let s: Spectral;
+
+  beforeEach(() => {
+    s = new Spectral();
+    s.setFunctions({ oasPathParam });
+    s.setRules({
+      'path-params': Object.assign(rules['path-params'], {
+        recommended: true,
+        type: RuleType[rules['path-params'].type],
+      }),
+    });
   });
 
   test('No error if templated path is not used', async () => {
@@ -255,44 +259,49 @@ describe('oasPathParam', () => {
   });
 
   test('Error if paths are functionally equivalent', async () => {
-    const results = await s.run({
-      paths: {
-        '/foo/{boo}': {
-          parameters: [
-            {
-              name: 'boo',
-              in: 'path',
-              required: true,
-            },
-          ],
-          get: {},
-        },
-        '/foo/{bar}': {
-          parameters: [
-            {
-              name: 'bar',
-              in: 'path',
-              required: true,
-            },
-          ],
-          get: {},
-        },
-      },
-    });
+    const results = await s.run(
+      new Document(
+        `{
+  "paths": {
+    "/foo/{boo}": {
+      "parameters": [
+        {
+          "name": "boo",
+          "in": "path",
+          "required": true
+        }
+      ],
+      "get": {}
+    },
+    "/foo/{bar}": {
+      "parameters": [
+        {
+          "name": "bar",
+          "in": "path",
+          "required": true
+        }
+      ],
+      "get": {}
+    }
+  }
+}`,
+        Parsers.Json,
+      ),
+    );
 
     expect(results).toEqual([
       {
         code: 'path-params',
         message: `The paths \`/foo/{boo}\` and \`/foo/{bar}\` are equivalent.`,
-        path: ['paths'],
+        path: ['paths', '/foo/{bar}'],
         range: {
           end: {
-            character: 15,
-            line: 20,
+            character: 5,
+            line: 21,
           },
           start: {
-            character: 10,
-            line: 1,
+            character: 18,
+            line: 12,
           },
         },
         severity: DiagnosticSeverity.Error,
diff --git a/src/rulesets/oas/functions/__tests__/oasTagDefined.test.ts b/src/rulesets/oas/functions/__tests__/oasTagDefined.test.ts
index 58d16182..f272628a 100644
--- a/src/rulesets/oas/functions/__tests__/oasTagDefined.test.ts
+++ b/src/rulesets/oas/functions/__tests__/oasTagDefined.test.ts
@@ -5,14 +5,17 @@ import { rules } from '../../index.json';
 import oasTagDefined from '../oasTagDefined';
 
 describe('oasTagDefined', () => {
-  const s = new Spectral();
+  let s: Spectral;
 
-  s.setFunctions({ oasTagDefined });
-  s.setRules({
-    'operation-tag-defined': Object.assign(rules['operation-tag-defined'], {
-      recommended: true,
-      type: RuleType[rules['operation-tag-defined'].type],
-    }),
+  beforeEach(() => {
+    s = new Spectral();
+    s.setFunctions({ oasTagDefined });
+    s.setRules({
+      'operation-tag-defined': Object.assign(rules['operation-tag-defined'], {
+        recommended: true,
+        type: RuleType[rules['operation-tag-defined'].type],
+      }),
+    });
   });
 
   test('validate a correct object', async () => {