@redocly/openapi-core 1.0.0-beta.91 → 1.0.0-beta.94

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 (45) hide show
  1. package/__tests__/normalizeVisitors.test.ts +1 -1
  2. package/__tests__/walk.test.ts +6 -6
  3. package/lib/config/all.js +1 -0
  4. package/lib/config/config.js +1 -1
  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/rules/common/assertions/asserts.d.ts +5 -0
  10. package/lib/rules/common/assertions/asserts.js +143 -0
  11. package/lib/rules/common/assertions/index.d.ts +2 -0
  12. package/lib/rules/common/assertions/index.js +52 -0
  13. package/lib/rules/common/assertions/utils.d.ts +20 -0
  14. package/lib/rules/common/assertions/utils.js +123 -0
  15. package/lib/rules/oas2/index.d.ts +1 -0
  16. package/lib/rules/oas2/index.js +2 -0
  17. package/lib/rules/oas3/index.js +2 -0
  18. package/lib/types/index.js +2 -2
  19. package/lib/types/oas3_1.js +31 -5
  20. package/lib/visitors.d.ts +2 -2
  21. package/lib/walk.d.ts +1 -0
  22. package/lib/walk.js +1 -1
  23. package/package.json +1 -1
  24. package/src/bundle.ts +1 -1
  25. package/src/config/__tests__/config.test.ts +256 -0
  26. package/src/config/all.ts +1 -0
  27. package/src/config/config.ts +15 -12
  28. package/src/config/minimal.ts +1 -0
  29. package/src/config/recommended.ts +1 -0
  30. package/src/config/rules.ts +11 -2
  31. package/src/lint.ts +3 -3
  32. package/src/rules/common/assertions/__tests__/asserts.test.ts +231 -0
  33. package/src/rules/common/assertions/__tests__/index.test.ts +65 -0
  34. package/src/rules/common/assertions/__tests__/utils.test.ts +89 -0
  35. package/src/rules/common/assertions/asserts.ts +137 -0
  36. package/src/rules/common/assertions/index.ts +75 -0
  37. package/src/rules/common/assertions/utils.ts +164 -0
  38. package/src/rules/oas2/index.ts +2 -0
  39. package/src/rules/oas3/__tests__/spec/servers.test.ts +1 -1
  40. package/src/rules/oas3/index.ts +2 -0
  41. package/src/types/index.ts +2 -2
  42. package/src/types/oas3_1.ts +32 -7
  43. package/src/visitors.ts +2 -2
  44. package/src/walk.ts +2 -1
  45. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,256 @@
1
+ import { Config, getMergedConfig } from '../config';
2
+
3
+ const testConfig: Config = {
4
+ rawConfig: {
5
+ apis: {
6
+ 'test@v1': {
7
+ root: 'resources/pets.yaml',
8
+ lint: { extends: [], rules: { 'operation-summary': 'warn' } },
9
+ },
10
+ },
11
+ organization: 'redocly-test',
12
+ lint: {
13
+ extends: [],
14
+ rules: { 'operation-summary': 'error', 'no-empty-servers': 'error' },
15
+ plugins: [],
16
+ },
17
+ },
18
+ configFile: 'redocly.yaml',
19
+ apis: {
20
+ 'test@v1': {
21
+ root: 'resources/pets.yaml',
22
+ lint: { extends: [], rules: { 'operation-summary': 'warn' } },
23
+ },
24
+ },
25
+ // @ts-ignore
26
+ lint: {
27
+ rawConfig: {
28
+ extends: [],
29
+ rules: { 'operation-summary': 'error', 'no-empty-servers': 'error' },
30
+ plugins: [],
31
+ },
32
+ configFile: 'redocly.yaml',
33
+ ignore: {},
34
+ _usedRules: new Set(),
35
+ _usedVersions: new Set(),
36
+ recommendedFallback: false,
37
+ plugins: [],
38
+ doNotResolveExamples: false,
39
+ rules: {
40
+ oas2: { 'operation-summary': 'error', 'no-empty-servers': 'error' },
41
+ oas3_0: { 'operation-summary': 'error', 'no-empty-servers': 'error' },
42
+ oas3_1: { 'operation-summary': 'error', 'no-empty-servers': 'error' },
43
+ },
44
+ preprocessors: { oas2: {}, oas3_0: {}, oas3_1: {} },
45
+ decorators: { oas2: {}, oas3_0: {}, oas3_1: {} },
46
+ },
47
+ 'features.openapi': {},
48
+ 'features.mockServer': {},
49
+ resolve: { http: { headers: [] } },
50
+ organization: 'redocly-test',
51
+ };
52
+
53
+ describe('getMergedConfig', () => {
54
+ it('should merge lint defined in "apis" section the root one', () => {
55
+ expect(getMergedConfig(testConfig, 'test@v1')).toMatchInlineSnapshot(`
56
+ Config {
57
+ "apis": Object {
58
+ "test@v1": Object {
59
+ "lint": Object {
60
+ "extends": Array [],
61
+ "rules": Object {
62
+ "operation-summary": "warn",
63
+ },
64
+ },
65
+ "root": "resources/pets.yaml",
66
+ },
67
+ },
68
+ "configFile": "redocly.yaml",
69
+ "features.mockServer": Object {},
70
+ "features.openapi": Object {},
71
+ "lint": LintConfig {
72
+ "_usedRules": Set {},
73
+ "_usedVersions": Set {},
74
+ "configFile": "redocly.yaml",
75
+ "decorators": Object {
76
+ "oas2": Object {},
77
+ "oas3_0": Object {},
78
+ "oas3_1": Object {},
79
+ },
80
+ "doNotResolveExamples": false,
81
+ "ignore": Object {},
82
+ "plugins": Array [],
83
+ "preprocessors": Object {
84
+ "oas2": Object {},
85
+ "oas3_0": Object {},
86
+ "oas3_1": Object {},
87
+ },
88
+ "rawConfig": Object {
89
+ "decorators": Object {},
90
+ "extends": Array [],
91
+ "plugins": Array [],
92
+ "preprocessors": Object {},
93
+ "rules": Object {
94
+ "no-empty-servers": "error",
95
+ "operation-summary": "warn",
96
+ },
97
+ },
98
+ "recommendedFallback": false,
99
+ "rules": Object {
100
+ "oas2": Object {
101
+ "no-empty-servers": "error",
102
+ "operation-summary": "warn",
103
+ },
104
+ "oas3_0": Object {
105
+ "no-empty-servers": "error",
106
+ "operation-summary": "warn",
107
+ },
108
+ "oas3_1": Object {
109
+ "no-empty-servers": "error",
110
+ "operation-summary": "warn",
111
+ },
112
+ },
113
+ },
114
+ "organization": "redocly-test",
115
+ "rawConfig": Object {
116
+ "apis": Object {
117
+ "test@v1": Object {
118
+ "lint": Object {
119
+ "extends": Array [],
120
+ "rules": Object {
121
+ "operation-summary": "warn",
122
+ },
123
+ },
124
+ "root": "resources/pets.yaml",
125
+ },
126
+ },
127
+ "features.mockServer": Object {},
128
+ "features.openapi": Object {},
129
+ "lint": Object {
130
+ "decorators": Object {},
131
+ "extends": Array [],
132
+ "plugins": Array [],
133
+ "preprocessors": Object {},
134
+ "rules": Object {
135
+ "no-empty-servers": "error",
136
+ "operation-summary": "warn",
137
+ },
138
+ },
139
+ "organization": "redocly-test",
140
+ },
141
+ "region": undefined,
142
+ "resolve": Object {
143
+ "http": Object {
144
+ "customFetch": undefined,
145
+ "headers": Array [],
146
+ },
147
+ },
148
+ }
149
+ `);
150
+ });
151
+ it('should take into account a config file', () => {
152
+ const result = getMergedConfig(testConfig, 'test@v1');
153
+ expect(result.configFile).toEqual('redocly.yaml');
154
+ expect(result.lint.configFile).toEqual('redocly.yaml');
155
+ });
156
+ it('should return the same config when there is no alias provided', () => {
157
+ expect(getMergedConfig(testConfig)).toEqual(testConfig);
158
+ });
159
+ it('should handle wrong alias - return the same lint, empty features', () => {
160
+ expect(getMergedConfig(testConfig, 'wrong-alias')).toMatchInlineSnapshot(`
161
+ Config {
162
+ "apis": Object {
163
+ "test@v1": Object {
164
+ "lint": Object {
165
+ "extends": Array [],
166
+ "rules": Object {
167
+ "operation-summary": "warn",
168
+ },
169
+ },
170
+ "root": "resources/pets.yaml",
171
+ },
172
+ },
173
+ "configFile": "redocly.yaml",
174
+ "features.mockServer": Object {},
175
+ "features.openapi": Object {},
176
+ "lint": LintConfig {
177
+ "_usedRules": Set {},
178
+ "_usedVersions": Set {},
179
+ "configFile": "redocly.yaml",
180
+ "decorators": Object {
181
+ "oas2": Object {},
182
+ "oas3_0": Object {},
183
+ "oas3_1": Object {},
184
+ },
185
+ "doNotResolveExamples": false,
186
+ "ignore": Object {},
187
+ "plugins": Array [],
188
+ "preprocessors": Object {
189
+ "oas2": Object {},
190
+ "oas3_0": Object {},
191
+ "oas3_1": Object {},
192
+ },
193
+ "rawConfig": Object {
194
+ "decorators": Object {},
195
+ "extends": Array [],
196
+ "plugins": Array [],
197
+ "preprocessors": Object {},
198
+ "rules": Object {
199
+ "no-empty-servers": "error",
200
+ "operation-summary": "error",
201
+ },
202
+ },
203
+ "recommendedFallback": false,
204
+ "rules": Object {
205
+ "oas2": Object {
206
+ "no-empty-servers": "error",
207
+ "operation-summary": "error",
208
+ },
209
+ "oas3_0": Object {
210
+ "no-empty-servers": "error",
211
+ "operation-summary": "error",
212
+ },
213
+ "oas3_1": Object {
214
+ "no-empty-servers": "error",
215
+ "operation-summary": "error",
216
+ },
217
+ },
218
+ },
219
+ "organization": "redocly-test",
220
+ "rawConfig": Object {
221
+ "apis": Object {
222
+ "test@v1": Object {
223
+ "lint": Object {
224
+ "extends": Array [],
225
+ "rules": Object {
226
+ "operation-summary": "warn",
227
+ },
228
+ },
229
+ "root": "resources/pets.yaml",
230
+ },
231
+ },
232
+ "features.mockServer": Object {},
233
+ "features.openapi": Object {},
234
+ "lint": Object {
235
+ "decorators": Object {},
236
+ "extends": Array [],
237
+ "plugins": Array [],
238
+ "preprocessors": Object {},
239
+ "rules": Object {
240
+ "no-empty-servers": "error",
241
+ "operation-summary": "error",
242
+ },
243
+ },
244
+ "organization": "redocly-test",
245
+ },
246
+ "region": undefined,
247
+ "resolve": Object {
248
+ "http": Object {
249
+ "customFetch": undefined,
250
+ "headers": Array [],
251
+ },
252
+ },
253
+ }
254
+ `);
255
+ });
256
+ });
package/src/config/all.ts CHANGED
@@ -19,6 +19,7 @@ export default {
19
19
  'operation-description': 'error',
20
20
  'operation-2xx-response': 'error',
21
21
  'operation-4xx-response': 'error',
22
+ 'assertions': 'error',
22
23
  'operation-operationId': 'error',
23
24
  'operation-summary': 'error',
24
25
  'operation-operationId-unique': 'error',
@@ -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
 
@@ -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,
@@ -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
+ });