@redocly/openapi-core 1.0.0-beta.90 → 1.0.0-beta.93

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/__tests__/__snapshots__/bundle.test.ts.snap +15 -13
  2. package/__tests__/ref-utils.test.ts +23 -1
  3. package/lib/config/all.js +1 -0
  4. package/lib/config/config.js +7 -12
  5. package/lib/config/minimal.js +1 -0
  6. package/lib/config/recommended.js +1 -0
  7. package/lib/config/rules.d.ts +1 -1
  8. package/lib/config/rules.js +10 -2
  9. package/lib/ref-utils.js +1 -1
  10. package/lib/rules/common/assertions/asserts.d.ts +5 -0
  11. package/lib/rules/common/assertions/asserts.js +143 -0
  12. package/lib/rules/common/assertions/index.d.ts +2 -0
  13. package/lib/rules/common/assertions/index.js +52 -0
  14. package/lib/rules/common/assertions/utils.d.ts +20 -0
  15. package/lib/rules/common/assertions/utils.js +123 -0
  16. package/lib/rules/oas2/index.d.ts +1 -0
  17. package/lib/rules/oas2/index.js +2 -0
  18. package/lib/rules/oas3/index.js +2 -0
  19. package/lib/visitors.d.ts +2 -2
  20. package/lib/walk.d.ts +1 -0
  21. package/lib/walk.js +1 -1
  22. package/package.json +1 -1
  23. package/src/bundle.ts +1 -1
  24. package/src/config/all.ts +1 -0
  25. package/src/config/config.ts +30 -24
  26. package/src/config/minimal.ts +1 -0
  27. package/src/config/recommended.ts +1 -0
  28. package/src/config/rules.ts +11 -2
  29. package/src/lint.ts +3 -3
  30. package/src/ref-utils.ts +1 -1
  31. package/src/rules/common/assertions/__tests__/asserts.test.ts +231 -0
  32. package/src/rules/common/assertions/__tests__/index.test.ts +65 -0
  33. package/src/rules/common/assertions/__tests__/utils.test.ts +89 -0
  34. package/src/rules/common/assertions/asserts.ts +137 -0
  35. package/src/rules/common/assertions/index.ts +75 -0
  36. package/src/rules/common/assertions/utils.ts +164 -0
  37. package/src/rules/oas2/index.ts +2 -0
  38. package/src/rules/oas3/index.ts +2 -0
  39. package/src/visitors.ts +2 -2
  40. package/src/walk.ts +2 -1
  41. package/tsconfig.tsbuildinfo +1 -1
@@ -1,7 +1,7 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import { dirname } from 'path';
4
- import { red, blue } from 'colorette';
4
+ import { red, blue, yellow, green } from 'colorette';
5
5
  import { parseYaml, stringifyYaml } from '../js-yaml';
6
6
  import { notUndefined, slash } from '../utils';
7
7
  import {
@@ -646,19 +646,22 @@ function assignExisting<T>(target: Record<string, T>, obj: Record<string, T>) {
646
646
 
647
647
  export function getMergedConfig(config: Config, entrypointAlias?: string): Config {
648
648
  return entrypointAlias
649
- ? new Config({
650
- ...config.rawConfig,
651
- lint: getMergedLintConfig(config, entrypointAlias),
652
- 'features.openapi': {
653
- ...config['features.openapi'],
654
- ...config.apis[entrypointAlias]?.['features.openapi'],
649
+ ? new Config(
650
+ {
651
+ ...config.rawConfig,
652
+ lint: getMergedLintConfig(config, entrypointAlias),
653
+ 'features.openapi': {
654
+ ...config['features.openapi'],
655
+ ...config.apis[entrypointAlias]?.['features.openapi'],
656
+ },
657
+ 'features.mockServer': {
658
+ ...config['features.mockServer'],
659
+ ...config.apis[entrypointAlias]?.['features.mockServer'],
660
+ },
661
+ // TODO: merge everything else here
655
662
  },
656
- 'features.mockServer': {
657
- ...config['features.mockServer'],
658
- ...config.apis[entrypointAlias]?.['features.mockServer'],
659
- },
660
- // TODO: merge everything else here
661
- })
663
+ config.configFile,
664
+ )
662
665
  : config;
663
666
  }
664
667
 
@@ -695,17 +698,20 @@ export function transformConfig(rawConfig: DeprecatedRawConfig | RawConfig): Raw
695
698
  throw new Error("Do not use 'referenceDocs' field. Use 'features.openapi' instead.\n");
696
699
  }
697
700
  const { apiDefinitions, referenceDocs, ...rest } = rawConfig as DeprecatedRawConfig & RawConfig;
698
- // TODO: put links to the changelog and uncomment this after successful release of ReferenceDocs/Redoc, Portal and Workflows
699
- // if (apiDefinitions) {
700
- // process.stderr.write(
701
- // `The ${yellow('apiDefinitions')} field is deprecated. Use ${green('apis')} instead, see changelog: <link>\n`
702
- // );
703
- // }
704
- // if (referenceDocs) {
705
- // process.stderr.write(
706
- // `The ${yellow('referenceDocs')} field is deprecated. Use ${green('features.openapi')} instead, see changelog: <link>\n`
707
- // );
708
- // }
701
+ if (apiDefinitions) {
702
+ process.stderr.write(
703
+ `The ${yellow('apiDefinitions')} field is deprecated. Use ${green(
704
+ 'apis',
705
+ )} instead. Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`,
706
+ );
707
+ }
708
+ if (referenceDocs) {
709
+ process.stderr.write(
710
+ `The ${yellow('referenceDocs')} field is deprecated. Use ${green(
711
+ 'features.openapi',
712
+ )} instead. Read more about this change: https://redocly.com/docs/api-registry/guides/migration-guide-config-file/#changed-properties\n`,
713
+ );
714
+ }
709
715
  return {
710
716
  'features.openapi': referenceDocs,
711
717
  apis: transformApiDefinitionsToApis(apiDefinitions),
@@ -18,6 +18,7 @@ export default {
18
18
  'operation-description': 'off',
19
19
  'operation-2xx-response': 'warn',
20
20
  'operation-4xx-response': 'off',
21
+ 'assertions': 'warn',
21
22
  'operation-operationId': 'warn',
22
23
  'operation-summary': 'warn',
23
24
  'operation-operationId-unique': 'warn',
@@ -17,6 +17,7 @@ export default {
17
17
  'path-parameters-defined': 'error',
18
18
  'operation-description': 'off',
19
19
  'operation-2xx-response': 'warn',
20
+ 'assertions': 'warn',
20
21
  'operation-4xx-response': 'warn',
21
22
  'operation-operationId': 'warn',
22
23
  'operation-summary': 'error',
@@ -24,14 +24,23 @@ export function initRules<T extends Function, P extends RuleSet<T>>(
24
24
  return undefined;
25
25
  }
26
26
 
27
- const visitor = rule(ruleSettings);
27
+ const visitors = rule(ruleSettings);
28
+
29
+ if (Array.isArray(visitors)) {
30
+ return visitors.map((visitor: any) => ({
31
+ severity: ruleSettings.severity,
32
+ ruleId,
33
+ visitor: visitor,
34
+ }))
35
+ }
28
36
 
29
37
  return {
30
38
  severity: ruleSettings.severity,
31
39
  ruleId,
32
- visitor,
40
+ visitor: visitors, // note: actually it is only one visitor object
33
41
  };
34
42
  }),
35
43
  )
44
+ .flatMap(visitor => visitor)
36
45
  .filter(notUndefined);
37
46
  }
package/src/lint.ts CHANGED
@@ -11,7 +11,7 @@ import { LintConfig, Config } from './config/config';
11
11
  import { normalizeTypes } from './types';
12
12
  import { initRules } from './config/rules';
13
13
  import { releaseAjvInstance } from './rules/ajv';
14
- import { detectOpenAPI, OasMajorVersion, OasVersion, openAPIMajor } from './oas-types';
14
+ import { detectOpenAPI, Oas3RuleSet, OasMajorVersion, OasVersion, openAPIMajor } from './oas-types';
15
15
  import { ConfigTypes } from './types/redocly-yaml';
16
16
  import { OasSpec } from './rules/common/spec';
17
17
  import { defaultPlugin } from './config/builtIn';
@@ -76,8 +76,8 @@ export async function lintDocument(opts: {
76
76
  };
77
77
 
78
78
  const preprocessors = initRules(rules as any, config, 'preprocessors', oasVersion);
79
- const regularRules = initRules(rules as any, config, 'rules', oasVersion);
80
- const normalizedVisitors = normalizeVisitors([...preprocessors, ...regularRules], types);
79
+ const regularRules = initRules(rules as Oas3RuleSet[], config, 'rules', oasVersion);
80
+ const normalizedVisitors = normalizeVisitors([...preprocessors, ...regularRules] as any, types);
81
81
  const resolvedRefMap = await resolveDocument({
82
82
  rootDocument: document,
83
83
  rootType: types.DefinitionRoot,
package/src/ref-utils.ts CHANGED
@@ -60,7 +60,7 @@ export function pointerBaseName(pointer: string) {
60
60
 
61
61
  export function refBaseName(ref: string) {
62
62
  const parts = ref.split(/[\/\\]/); // split by '\' and '/'
63
- return parts[parts.length - 1].split('.')[0];
63
+ return parts[parts.length - 1].replace(/\.[^.]+$/, ''); // replace extension with empty string
64
64
  }
65
65
 
66
66
  export function isAbsoluteUrl(ref: string) {
@@ -0,0 +1,231 @@
1
+ import { asserts } from '../asserts';
2
+
3
+ describe('oas3 assertions', () => {
4
+ describe('generic rules', () => {
5
+ const fakeNode = {
6
+ foo: '',
7
+ bar: '',
8
+ baz: '',
9
+ };
10
+
11
+ describe('pattern', () => {
12
+ it('value should match regex pattern', () => {
13
+ expect(asserts.pattern('test string', '/test/')).toBeTruthy();
14
+ expect(asserts.pattern('test string', '/test me/')).toBeFalsy();
15
+ expect(asserts.pattern(['test string', 'test me'], '/test/')).toBeTruthy();
16
+ expect(asserts.pattern(['test string', 'test me'], '/test me/')).toBeFalsy();
17
+ });
18
+ });
19
+
20
+ describe('enum', () => {
21
+ it('value should be among predefined keys', () => {
22
+ expect(asserts.enum('test', ['test', 'example'])).toBeTruthy();
23
+ expect(asserts.enum(['test'], ['test', 'example'])).toBeTruthy();
24
+ expect(asserts.enum(['test', 'example'], ['test', 'example'])).toBeTruthy();
25
+ expect(asserts.enum(['test', 'example', 'foo'], ['test', 'example'])).toBeFalsy();
26
+ expect(asserts.enum('test', ['foo', 'example'])).toBeFalsy();
27
+ expect(asserts.enum(['test', 'foo'], ['test', 'example'])).toBeFalsy();
28
+ });
29
+ });
30
+
31
+ describe('defined', () => {
32
+ it('value should be defined', () => {
33
+ expect(asserts.defined('test', true)).toBeTruthy();
34
+ expect(asserts.defined(undefined, true)).toBeFalsy();
35
+ });
36
+ it('value should be undefined', () => {
37
+ expect(asserts.defined(undefined, false)).toBeTruthy();
38
+ expect(asserts.defined('test', false)).toBeFalsy();
39
+ });
40
+ });
41
+
42
+ describe('undefined', () => {
43
+ it('value should be undefined', () => {
44
+ expect(asserts.undefined(undefined, true)).toBeTruthy();
45
+ expect(asserts.undefined('test', true)).toBeFalsy();
46
+ });
47
+ it('value should be defined', () => {
48
+ expect(asserts.undefined('test', false)).toBeTruthy();
49
+ expect(asserts.undefined(undefined, false)).toBeFalsy();
50
+ });
51
+ });
52
+
53
+ describe('required', () => {
54
+ it('values should be required', () => {
55
+ expect(asserts.required(['one', 'two', 'three'], ['one', 'two'])).toBeTruthy();
56
+ expect(asserts.required(['one', 'two'], ['one', 'two', 'three'])).toBeFalsy();
57
+ });
58
+ });
59
+
60
+ describe('nonEmpty', () => {
61
+ it('value should not be empty', () => {
62
+ expect(asserts.nonEmpty('test', true)).toBeTruthy();
63
+ expect(asserts.nonEmpty('', true)).toBeFalsy();
64
+ expect(asserts.nonEmpty(null, true)).toBeFalsy();
65
+ expect(asserts.nonEmpty(undefined, true)).toBeFalsy();
66
+ });
67
+ it('value should be empty', () => {
68
+ expect(asserts.nonEmpty('', false)).toBeTruthy();
69
+ expect(asserts.nonEmpty(null, false)).toBeTruthy();
70
+ expect(asserts.nonEmpty(undefined, false)).toBeTruthy();
71
+ expect(asserts.nonEmpty('test', false)).toBeFalsy();
72
+ });
73
+ });
74
+
75
+ describe('minLength', () => {
76
+ it('value should have less or equal than 5 symbols length', () => {
77
+ expect(asserts.minLength('test', 5)).toBeFalsy();
78
+ expect(asserts.minLength([1, 2, 3, 4], 5)).toBeFalsy();
79
+ expect(asserts.minLength([1, 2, 3, 4, 5], 5)).toBeTruthy();
80
+ expect(asserts.minLength([1, 2, 3, 4, 5, 6], 5)).toBeTruthy();
81
+ expect(asserts.minLength('example', 5)).toBeTruthy();
82
+ expect(asserts.minLength([], 5)).toBeFalsy();
83
+ expect(asserts.minLength('', 5)).toBeFalsy();
84
+ });
85
+ });
86
+
87
+ describe('maxLength', () => {
88
+ it('value should have more or equal than 5 symbols length', () => {
89
+ expect(asserts.maxLength('test', 5)).toBeTruthy();
90
+ expect(asserts.maxLength([1, 2, 3, 4], 5)).toBeTruthy();
91
+ expect(asserts.maxLength([1, 2, 3, 4, 5], 5)).toBeTruthy();
92
+ expect(asserts.maxLength([1, 2, 3, 4, 5, 6], 5)).toBeFalsy();
93
+ expect(asserts.maxLength('example', 5)).toBeFalsy();
94
+ expect(asserts.maxLength([], 5)).toBeTruthy();
95
+ expect(asserts.maxLength('', 5)).toBeTruthy();
96
+ });
97
+ });
98
+
99
+ describe('casing', () => {
100
+ it('value should be camelCase', () => {
101
+ expect(asserts.casing(['testExample', 'fooBar'], 'camelCase')).toBeTruthy();
102
+ expect(asserts.casing(['testExample', 'FooBar'], 'camelCase')).toBeFalsy();
103
+ expect(asserts.casing('testExample', 'camelCase')).toBeTruthy();
104
+ expect(asserts.casing('TestExample', 'camelCase')).toBeFalsy();
105
+ expect(asserts.casing('test-example', 'camelCase')).toBeFalsy();
106
+ expect(asserts.casing('test_example', 'camelCase')).toBeFalsy();
107
+ });
108
+ it('value should be PascalCase', () => {
109
+ expect(asserts.casing('TestExample', 'PascalCase')).toBeTruthy();
110
+ expect(asserts.casing(['TestExample', 'FooBar'], 'PascalCase')).toBeTruthy();
111
+ expect(asserts.casing(['TestExample', 'fooBar'], 'PascalCase')).toBeFalsy();
112
+ expect(asserts.casing('testExample', 'PascalCase')).toBeFalsy();
113
+ expect(asserts.casing('test-example', 'PascalCase')).toBeFalsy();
114
+ expect(asserts.casing('test_example', 'PascalCase')).toBeFalsy();
115
+ });
116
+ it('value should be kebab-case', () => {
117
+ expect(asserts.casing('test-example', 'kebab-case')).toBeTruthy();
118
+ expect(asserts.casing(['test-example', 'foo-bar'], 'kebab-case')).toBeTruthy();
119
+ expect(asserts.casing(['test-example', 'foo_bar'], 'kebab-case')).toBeFalsy();
120
+ expect(asserts.casing('testExample', 'kebab-case')).toBeFalsy();
121
+ expect(asserts.casing('TestExample', 'kebab-case')).toBeFalsy();
122
+ expect(asserts.casing('test_example', 'kebab-case')).toBeFalsy();
123
+ });
124
+ it('value should be snake_case', () => {
125
+ expect(asserts.casing('test_example', 'snake_case')).toBeTruthy();
126
+ expect(asserts.casing(['test_example', 'foo_bar'], 'snake_case')).toBeTruthy();
127
+ expect(asserts.casing(['test_example', 'foo-bar'], 'snake_case')).toBeFalsy();
128
+ expect(asserts.casing('testExample', 'snake_case')).toBeFalsy();
129
+ expect(asserts.casing('TestExample', 'snake_case')).toBeFalsy();
130
+ expect(asserts.casing('test-example', 'snake_case')).toBeFalsy();
131
+ });
132
+ it('value should be MACRO_CASE', () => {
133
+ expect(asserts.casing('TEST_EXAMPLE', 'MACRO_CASE')).toBeTruthy();
134
+ expect(asserts.casing(['TEST_EXAMPLE', 'FOO_BAR'], 'MACRO_CASE')).toBeTruthy();
135
+ expect(asserts.casing(['TEST_EXAMPLE', 'FOO-BAR'], 'MACRO_CASE')).toBeFalsy();
136
+ expect(asserts.casing('TEST_EXAMPLE_', 'MACRO_CASE')).toBeFalsy();
137
+ expect(asserts.casing('_TEST_EXAMPLE', 'MACRO_CASE')).toBeFalsy();
138
+ expect(asserts.casing('TEST__EXAMPLE', 'MACRO_CASE')).toBeFalsy();
139
+ expect(asserts.casing('TEST-EXAMPLE', 'MACRO_CASE')).toBeFalsy();
140
+ expect(asserts.casing('testExample', 'MACRO_CASE')).toBeFalsy();
141
+ expect(asserts.casing('TestExample', 'MACRO_CASE')).toBeFalsy();
142
+ expect(asserts.casing('test-example', 'MACRO_CASE')).toBeFalsy();
143
+ });
144
+ it('value should be COBOL-CASE', () => {
145
+ expect(asserts.casing('TEST-EXAMPLE', 'COBOL-CASE')).toBeTruthy();
146
+ expect(asserts.casing(['TEST-EXAMPLE', 'FOO-BAR'], 'COBOL-CASE')).toBeTruthy();
147
+ expect(asserts.casing(['TEST-EXAMPLE', 'FOO_BAR'], 'COBOL-CASE')).toBeFalsy();
148
+ expect(asserts.casing('TEST-EXAMPLE-', 'COBOL-CASE')).toBeFalsy();
149
+ expect(asserts.casing('0TEST-EXAMPLE', 'COBOL-CASE')).toBeFalsy();
150
+ expect(asserts.casing('-TEST-EXAMPLE', 'COBOL-CASE')).toBeFalsy();
151
+ expect(asserts.casing('TEST--EXAMPLE', 'COBOL-CASE')).toBeFalsy();
152
+ expect(asserts.casing('TEST_EXAMPLE', 'COBOL-CASE')).toBeFalsy();
153
+ expect(asserts.casing('testExample', 'COBOL-CASE')).toBeFalsy();
154
+ expect(asserts.casing('TestExample', 'COBOL-CASE')).toBeFalsy();
155
+ expect(asserts.casing('test-example', 'COBOL-CASE')).toBeFalsy();
156
+ });
157
+ it('value should be flatcase', () => {
158
+ expect(asserts.casing('testexample', 'flatcase')).toBeTruthy();
159
+ expect(asserts.casing(['testexample', 'foobar'], 'flatcase')).toBeTruthy();
160
+ expect(asserts.casing(['testexample', 'foo_bar'], 'flatcase')).toBeFalsy();
161
+ expect(asserts.casing('testexample_', 'flatcase')).toBeFalsy();
162
+ expect(asserts.casing('0testexample', 'flatcase')).toBeFalsy();
163
+ expect(asserts.casing('testExample', 'flatcase')).toBeFalsy();
164
+ expect(asserts.casing('TestExample', 'flatcase')).toBeFalsy();
165
+ expect(asserts.casing('test-example', 'flatcase')).toBeFalsy();
166
+ });
167
+ });
168
+
169
+ describe.skip('sortOrder', () => {
170
+ it('value should be ordered in ASC direction', () => {
171
+ expect(asserts.sortOrder(['example', 'foo', 'test'], 'asc')).toBeTruthy();
172
+ expect(asserts.sortOrder(['example', 'foo', 'test'], { direction: 'asc' })).toBeTruthy();
173
+ expect(asserts.sortOrder(['example'], 'asc')).toBeTruthy();
174
+ expect(asserts.sortOrder(['example', 'test', 'foo'], 'asc')).toBeFalsy();
175
+ expect(asserts.sortOrder(['example', 'foo', 'test'], 'desc')).toBeFalsy();
176
+ expect(
177
+ asserts.sortOrder([{ name: 'bar' }, { name: 'baz' }, { name: 'foo' }], {
178
+ direction: 'asc',
179
+ property: 'name',
180
+ }),
181
+ ).toBeTruthy();
182
+ expect(
183
+ asserts.sortOrder([{ name: 'bar' }, { name: 'baz' }, { name: 'foo' }], {
184
+ direction: 'desc',
185
+ property: 'name',
186
+ }),
187
+ ).toBeFalsy();
188
+ });
189
+ it('value should be ordered in DESC direction', () => {
190
+ expect(asserts.sortOrder(['test', 'foo', 'example'], 'desc')).toBeTruthy();
191
+ expect(asserts.sortOrder(['test', 'foo', 'example'], { direction: 'desc' })).toBeTruthy();
192
+ expect(asserts.sortOrder(['example'], 'desc')).toBeTruthy();
193
+ expect(asserts.sortOrder(['example', 'test', 'foo'], 'desc')).toBeFalsy();
194
+ expect(asserts.sortOrder(['test', 'foo', 'example'], 'asc')).toBeFalsy();
195
+ expect(
196
+ asserts.sortOrder([{ name: 'foo' }, { name: 'baz' }, { name: 'bar' }], {
197
+ direction: 'desc',
198
+ property: 'name',
199
+ }),
200
+ ).toBeTruthy();
201
+ expect(
202
+ asserts.sortOrder([{ name: 'foo' }, { name: 'baz' }, { name: 'bar' }], {
203
+ direction: 'asc',
204
+ property: 'name',
205
+ }),
206
+ ).toBeFalsy();
207
+ });
208
+ });
209
+
210
+ describe('mutuallyExclusive', () => {
211
+ it('node should not have more than one property from predefined list', () => {
212
+ expect(asserts.mutuallyExclusive(Object.keys(fakeNode), ['foo', 'test'])).toBeTruthy();
213
+ expect(asserts.mutuallyExclusive(Object.keys(fakeNode), [])).toBeTruthy();
214
+ expect(asserts.mutuallyExclusive(Object.keys(fakeNode), ['foo', 'bar'])).toBeFalsy();
215
+ expect(
216
+ asserts.mutuallyExclusive(Object.keys(fakeNode), ['foo', 'bar', 'test']),
217
+ ).toBeFalsy();
218
+ });
219
+ });
220
+
221
+ describe('mutuallyRequired', () => {
222
+ it('node should have all the properties from predefined list', () => {
223
+ expect(asserts.mutuallyRequired(Object.keys(fakeNode), ['foo', 'bar'])).toBeTruthy();
224
+ expect(asserts.mutuallyRequired(Object.keys(fakeNode), ['foo', 'bar', 'baz'])).toBeTruthy();
225
+ expect(asserts.mutuallyRequired(Object.keys(fakeNode), [])).toBeTruthy();
226
+ expect(asserts.mutuallyRequired(Object.keys(fakeNode), ['foo', 'test'])).toBeFalsy();
227
+ expect(asserts.mutuallyRequired(Object.keys(fakeNode), ['foo', 'bar', 'test'])).toBeFalsy();
228
+ });
229
+ });
230
+ });
231
+ });
@@ -0,0 +1,65 @@
1
+ import { Assertions } from '../.';
2
+
3
+ const opts = {
4
+ '0': {
5
+ subject: 'Operation',
6
+ property: 'summary',
7
+ description: 'example warn text',
8
+ severity: 'warn',
9
+ pattern: '/example/',
10
+ },
11
+ '1': {
12
+ subject: 'PathItem',
13
+ context: [{ type: 'Operation', matchParentKeys: ['post'] }],
14
+ description: 'example warn text',
15
+ severity: 'warn',
16
+ mutuallyExclusive: ['summary', 'security'],
17
+ },
18
+ '2': {
19
+ subject: ['PathItem'],
20
+ context: [{ type: 'Operation' }],
21
+ property: 'tags',
22
+ description: 'example warn text',
23
+ severity: 'warn',
24
+ sortOrder: 'desc',
25
+ },
26
+ '3': {
27
+ subject: ['Foo'],
28
+ context: [{ type: 'Bar' }, { type: 'Baz' }],
29
+ property: 'test',
30
+ description: 'example warn text',
31
+ severity: 'warn',
32
+ sortOrder: 'desc',
33
+ },
34
+ };
35
+
36
+ describe('Oas3 assertions', () => {
37
+ it('should return the right visitor structure', () => {
38
+ const visitors = Assertions(opts) as any;
39
+ expect(visitors).toMatchInlineSnapshot(`
40
+ Array [
41
+ Object {
42
+ "Operation": [Function],
43
+ },
44
+ Object {
45
+ "Operation": Object {
46
+ "PathItem": [Function],
47
+ "skip": [Function],
48
+ },
49
+ },
50
+ Object {
51
+ "Operation": Object {
52
+ "PathItem": [Function],
53
+ },
54
+ },
55
+ Object {
56
+ "Bar": Object {
57
+ "Baz": Object {
58
+ "Foo": [Function],
59
+ },
60
+ },
61
+ },
62
+ ]
63
+ `);
64
+ });
65
+ });
@@ -0,0 +1,89 @@
1
+ import { isOrdered, buildVisitorObject, getIntersectionLength } from '../utils';
2
+
3
+ describe('Oas3 assertions', () => {
4
+ describe('Utils', () => {
5
+ describe('getCounts', () => {
6
+ it('should return the right counts', () => {
7
+ const arr = ['foo', 'bar', 'baz'];
8
+ expect(getIntersectionLength(arr, ['foo'])).toBe(1);
9
+ expect(getIntersectionLength(arr, ['foo', 'bar', 'baz'])).toBe(3);
10
+ expect(getIntersectionLength(arr, ['foo', 'test', 'baz'])).toBe(2);
11
+ expect(getIntersectionLength(arr, ['example', 'test'])).toBe(0);
12
+ });
13
+ });
14
+
15
+ describe('isOrdered', () => {
16
+ it('should say if array is ordered or not in specific direction', () => {
17
+ expect(isOrdered(['example', 'foo', 'test'], 'asc')).toBeTruthy();
18
+ expect(isOrdered(['example'], 'asc')).toBeTruthy();
19
+ expect(isOrdered(['test', 'foo', 'example'], 'desc')).toBeTruthy();
20
+ expect(isOrdered(['example'], 'desc')).toBeTruthy();
21
+ expect(isOrdered(['example', 'test', 'foo'], 'asc')).toBeFalsy();
22
+ expect(isOrdered(['example', 'foo', 'test'], 'desc')).toBeFalsy();
23
+ });
24
+ });
25
+
26
+ describe('buildVisitorObject', () => {
27
+ it('should return a consistent visitor structure', () => {
28
+ const context = [
29
+ {
30
+ type: 'Foo',
31
+ matchParentKeys: ['test'],
32
+ },
33
+ {
34
+ type: 'Bar',
35
+ matchParentKeys: ['test'],
36
+ },
37
+ {
38
+ type: 'Roof',
39
+ matchParentKeys: ['test'],
40
+ },
41
+ ];
42
+
43
+ const visitors = buildVisitorObject('Bar', context, () => {}) as any;
44
+
45
+ expect(visitors).toMatchInlineSnapshot(`
46
+ Object {
47
+ "Foo": Object {
48
+ "Bar": Object {
49
+ "Roof": Object {
50
+ "Bar": [Function],
51
+ "skip": [Function],
52
+ },
53
+ "skip": [Function],
54
+ },
55
+ "skip": [Function],
56
+ },
57
+ }
58
+ `);
59
+ });
60
+
61
+ it('should return the right visitor structure', () => {
62
+ const context = [
63
+ {
64
+ type: 'Operation',
65
+ matchParentKeys: ['put'],
66
+ },
67
+ {
68
+ type: 'ResponsesMap',
69
+ matchParentKeys: [201, 200],
70
+ },
71
+ ];
72
+
73
+ const visitors = buildVisitorObject('MediaTypeMap', context, () => {}) as any;
74
+
75
+ expect(visitors).toMatchInlineSnapshot(`
76
+ Object {
77
+ "Operation": Object {
78
+ "ResponsesMap": Object {
79
+ "MediaTypeMap": [Function],
80
+ "skip": [Function],
81
+ },
82
+ "skip": [Function],
83
+ },
84
+ }
85
+ `);
86
+ });
87
+ });
88
+ });
89
+ });