diff --git a/src/rulesets/oas/__tests__/example-value-or-externalValue.ts b/src/rulesets/oas/__tests__/example-value-or-externalValue.ts index 796ccc075..8b24abc91 100644 --- a/src/rulesets/oas/__tests__/example-value-or-externalValue.ts +++ b/src/rulesets/oas/__tests__/example-value-or-externalValue.ts @@ -12,41 +12,82 @@ describe('example-value-or-externalValue', () => { }); test('validate if just externalValue', async () => { - const results = await s.run({ examples: { first: { externalValue: 'value' } } }); + const results = await s.run({ components: { examples: { first: { externalValue: 'value' } } } }); expect(results.length).toEqual(0); }); test('validate if just value', async () => { - const results = await s.run({ examples: { first: { value: 'value' } } }); + const results = await s.run({ components: { examples: { first: { value: 'value' } } } }); + expect(results.length).toEqual(0); + }); + + test('validate if example on top level', async () => { + const results = await s.run({ examples: { first: { value: 'value', externalValue: 'value' } } }); + expect(results.length).toEqual(0); + }); + + test('validate if examples properties in examples', async () => { + const results = await s.run({ + components: { + examples: { + first: { + value: { + examples: { + a: 'b', + }, + }, + }, + second: { + value: { + components: { + examples: { + value: 'value', + externalValue: 'value', + }, + }, + }, + }, + third: { + value: { + examples: { + a: 'b', + }, + }, + }, + }, + }, + }); expect(results.length).toEqual(0); }); test('multiple examples - validate all value or externalValue', async () => { const results = await s.run({ - examples: { - first: { value: 'value1' }, - second: { externalValue: 'external-value2' }, - third: { value: 'value3' }, + components: { + examples: { + first: { value: 'value1' }, + second: { externalValue: 'external-value2' }, + third: { value: 'value3' }, + }, }, }); expect(results.length).toEqual(0); }); test('return warnings if missing externalValue and value', async () => { - const results = await s.run({ examples: { first: {} } }); + const results = await s.run({ components: { examples: { first: {} } } }); expect(results).toEqual([ { code: 'example-value-or-externalValue', message: 'Example should have either a `value` or `externalValue` field.', - path: ['examples', 'first'], + path: ['components', 'examples', 'first'], range: { end: { - character: 15, - line: 2, + character: 17, + line: 3, }, start: { - character: 12, - line: 2, + character: 14, + line: 3, }, }, severity: DiagnosticSeverity.Warning, @@ -56,20 +97,108 @@ describe('example-value-or-externalValue', () => { test('multiple examples - return warnings if missing externalValue and value in one', async () => { const results = await s.run({ - examples: { first: { value: 'value1' }, second: { externalValue: 'external-value2' }, third: {} }, + components: { examples: { first: { value: 'value1' }, second: { externalValue: 'external-value2' }, third: {} } }, }); expect(results).toEqual([ { code: 'example-value-or-externalValue', message: 'Example should have either a `value` or `externalValue` field.', - path: ['examples', 'third'], + path: ['components', 'examples', 'third'], range: { end: { - character: 15, + character: 17, + line: 9, + }, + start: { + character: 14, + line: 9, + }, + }, + severity: DiagnosticSeverity.Warning, + }, + ]); + }); + + test('return warnings if both externalValue and value', async () => { + const results = await s.run({ + components: { examples: { first: { externalValue: 'externalValue', value: 'value' } } }, + }); + expect(results).toEqual([ + { + code: 'example-value-or-externalValue', + message: 'Example should have either a `value` or `externalValue` field.', + path: ['components', 'examples', 'first'], + range: { + end: { + character: 24, + line: 5, + }, + start: { + character: 14, + line: 3, + }, + }, + severity: DiagnosticSeverity.Warning, + }, + ]); + }); + + test('multiple examples - return warnings if both externalValue and value in one (in components)', async () => { + const results = await s.run({ + components: { + examples: { + first: { value: 'value1' }, + second: { externalValue: 'external-value2', value: 'value2' }, + third: { externalValue: 'external-value3' }, + }, + }, + }); + expect(results).toEqual([ + { + code: 'example-value-or-externalValue', + message: 'Example should have either a `value` or `externalValue` field.', + path: ['components', 'examples', 'second'], + range: { + end: { + character: 25, line: 8, }, start: { - character: 12, + character: 15, + line: 6, + }, + }, + severity: DiagnosticSeverity.Warning, + }, + ]); + }); + + test('multiple examples - return warnings if both externalValue and value in one (in headers)', async () => { + const results = await s.run({ + components: { + headers: { + headerName: { + examples: { + first: { value: 'value1' }, + second: { externalValue: 'external-value2', value: 'value2' }, + third: { externalValue: 'external-value3' }, + }, + }, + }, + }, + }); + expect(results).toEqual([ + { + code: 'example-value-or-externalValue', + message: 'Example should have either a `value` or `externalValue` field.', + path: ['components', 'headers', 'headerName', 'examples', 'second'], + range: { + end: { + character: 29, + line: 10, + }, + start: { + character: 19, line: 8, }, }, @@ -78,21 +207,33 @@ describe('example-value-or-externalValue', () => { ]); }); - test('return warnings if both externalValue and value', async () => { - const results = await s.run({ examples: { first: { externalValue: 'externalValue', value: 'value' } } }); + test('multiple examples - return warnings if both externalValue and value in one (in parameters)', async () => { + const results = await s.run({ + components: { + parameters: { + parameterName: { + examples: { + first: { value: 'value1' }, + second: { externalValue: 'external-value2', value: 'value2' }, + third: { externalValue: 'external-value3' }, + }, + }, + }, + }, + }); expect(results).toEqual([ { code: 'example-value-or-externalValue', message: 'Example should have either a `value` or `externalValue` field.', - path: ['examples', 'first'], + path: ['components', 'parameters', 'parameterName', 'examples', 'second'], range: { end: { - character: 22, - line: 4, + character: 29, + line: 10, }, start: { - character: 12, - line: 2, + character: 19, + line: 8, }, }, severity: DiagnosticSeverity.Warning, @@ -100,27 +241,41 @@ describe('example-value-or-externalValue', () => { ]); }); - test('multiple examples - return warnings if both externalValue and value in one', async () => { + test('multiple examples - return warnings if both externalValue and value in one (in content)', async () => { const results = await s.run({ - examples: { - first: { value: 'value1' }, - second: { externalValue: 'external-value2', value: 'value2' }, - third: { externalValue: 'external-value3' }, + paths: { + '/path': { + get: { + responses: { + 200: { + content: { + 'application/json': { + examples: { + first: { value: 'value1' }, + second: { externalValue: 'external-value2', value: 'value2' }, + third: { externalValue: 'external-value3' }, + }, + }, + }, + }, + }, + }, + }, }, }); expect(results).toEqual([ { code: 'example-value-or-externalValue', message: 'Example should have either a `value` or `externalValue` field.', - path: ['examples', 'second'], + path: ['paths', '/path', 'get', 'responses', '200', 'content', 'application/json', 'examples', 'second'], range: { end: { - character: 23, - line: 7, + character: 37, + line: 14, }, start: { - character: 13, - line: 5, + character: 27, + line: 12, }, }, severity: DiagnosticSeverity.Warning, diff --git a/src/rulesets/oas/index.json b/src/rulesets/oas/index.json index 31df2cf16..be7aafbd1 100644 --- a/src/rulesets/oas/index.json +++ b/src/rulesets/oas/index.json @@ -115,7 +115,15 @@ "description": "Example should have either a `value` or `externalValue` field.", "recommended": true, "type": "style", - "given": "$..examples.*", + "given": [ + "$.components.examples.*", + "$.paths..content.*.examples.*", + "$.components..content.*.examples.*", + "$.paths..parameters.*.examples.*", + "$.components..parameters.*.examples.*", + "$.paths..headers.*.examples.*", + "$.components..headers.*.examples.*" + ], "then": { "function": "xor", "functionOptions": {