Skip to content

Commit 39205c3

Browse files
authored
fix: report component renaming conflicts for same-name components from different files (#2706)
1 parent ccd48c2 commit 39205c3

11 files changed

Lines changed: 217 additions & 28 deletions

.changeset/quiet-snakes-buy.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@redocly/openapi-core": patch
3+
"@redocly/cli": patch
4+
---
5+
6+
Fixed an issue where `--component-renaming-conflicts-severity` ignored conflicts when different files had components with the same name but different content.
7+
8+
**Warning:** Autogenrated component names and `$ref` paths in bundled documents may differ from older releases.

packages/core/src/__tests__/__snapshots__/bundle-oas.test.ts.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ components:
2626
$ref: '#/components/schemas/schema-a'
2727
examples:
2828
first:
29-
$ref: '#/components/examples/param-a-first'
29+
$ref: '#/components/examples/first-2'
3030
second:
3131
$ref: '#/components/examples/second'
3232
path-param:
@@ -41,7 +41,7 @@ components:
4141
examples:
4242
first:
4343
value: b1
44-
param-a-first:
44+
first-2:
4545
value: a1
4646
second:
4747
value: a2

packages/core/src/__tests__/__snapshots__/bundle.test.ts.snap

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`bundle > should bundle external pointer refs and warn for conflicting names 1`] = `
4+
openapi: 3.1.0
5+
paths:
6+
/foo:
7+
put:
8+
parameters:
9+
- $ref: '#/components/parameters/User-2'
10+
get:
11+
parameters:
12+
- $ref: '#/components/parameters/User'
13+
components:
14+
parameters:
15+
User:
16+
name: test
17+
in: query
18+
description: test-B
19+
User-2:
20+
name: test
21+
in: path
22+
description: test-A
23+
24+
`;
25+
326
exports[`bundle > should bundle external refs 1`] = `
427
openapi: 3.0.0
528
paths:
@@ -26,7 +49,7 @@ components:
2649
$ref: '#/components/schemas/schema-a'
2750
examples:
2851
first:
29-
$ref: '#/components/examples/param-a-first'
52+
$ref: '#/components/examples/first-2'
3053
second:
3154
$ref: '#/components/examples/second'
3255
path-param:
@@ -41,7 +64,7 @@ components:
4164
examples:
4265
first:
4366
value: b1
44-
param-a-first:
67+
first-2:
4568
value: a1
4669
second:
4770
value: a2
@@ -124,6 +147,51 @@ components:
124147
125148
`;
126149

150+
exports[`bundle > should keep dotted JSON pointer schema keys and rename conflicting User schemas 1`] = `
151+
openapi: 3.0.0
152+
info:
153+
title: Test ref with dots in component names
154+
version: '1.0'
155+
description: Demo
156+
license:
157+
name: DEMO
158+
url: https://demo.com
159+
servers:
160+
- url: http://demo.com/api
161+
paths:
162+
/org-user:
163+
get:
164+
responses:
165+
'200':
166+
description: ok
167+
content:
168+
application/json:
169+
schema:
170+
$ref: '#/components/schemas/my.org.User'
171+
post:
172+
responses:
173+
'200':
174+
description: ok
175+
content:
176+
application/json:
177+
schema:
178+
additionalProperties:
179+
$ref: '#/components/schemas/my.User'
180+
components:
181+
schemas:
182+
my.org.User:
183+
type: object
184+
properties:
185+
orgId:
186+
type: string
187+
my.User:
188+
type: object
189+
properties:
190+
displayName:
191+
type: string
192+
193+
`;
194+
127195
exports[`bundle > should normalize self-file explicit $ref in nested referenced file 1`] = `
128196
openapi: 3.0.0
129197
info:

packages/core/src/__tests__/bundle-oas.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ describe('bundle-oas', () => {
4747
config: await createEmptyRedoclyConfig({}),
4848
ref: path.join(__dirname, 'fixtures/refs/openapi-with-external-refs.yaml'),
4949
});
50-
expect(problems).toHaveLength(0);
50+
expect(problems).toHaveLength(1);
51+
expect(problems[0].severity).toBe('warn');
52+
expect(problems[0].message).toEqual(
53+
`Two schemas are referenced with the same name but different content. Renamed first to first-2.`
54+
);
5155
expect(res.parsed).toMatchSnapshot();
5256
});
5357

packages/core/src/__tests__/bundle.test.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ describe('bundle', () => {
6464
config: await createConfig({}),
6565
ref: path.join(__dirname, 'fixtures/refs/openapi-with-external-refs.yaml'),
6666
});
67-
expect(problems).toHaveLength(0);
67+
expect(problems).toHaveLength(1);
68+
expect(problems[0].severity).toBe('warn');
69+
expect(problems[0].message).toEqual(
70+
`Two schemas are referenced with the same name but different content. Renamed first to first-2.`
71+
);
6872
expect(res.parsed).toMatchSnapshot();
6973
});
7074

@@ -119,6 +123,67 @@ describe('bundle', () => {
119123
);
120124
});
121125

126+
it('should bundle external pointer refs and warn for conflicting names', async () => {
127+
const { bundle: res, problems } = await bundle({
128+
config: await createConfig({}),
129+
ref: path.join(
130+
__dirname,
131+
'fixtures/refs/openapi-with-external-refs-pointer-conflicting-names.yaml'
132+
),
133+
});
134+
expect(problems).toHaveLength(1);
135+
expect(problems[0].severity).toBe('warn');
136+
expect(problems[0].message).toEqual(
137+
`Two schemas are referenced with the same name but different content. Renamed User to User-2.`
138+
);
139+
expect(res.parsed).toMatchSnapshot();
140+
});
141+
142+
it('should bundle external pointer refs and do not show warnings for conflicting names', async () => {
143+
const { problems } = await bundle({
144+
config: await createConfig({}),
145+
ref: path.join(
146+
__dirname,
147+
'fixtures/refs/openapi-with-external-refs-pointer-conflicting-names.yaml'
148+
),
149+
componentRenamingConflicts: 'off',
150+
});
151+
expect(problems).toHaveLength(0);
152+
});
153+
154+
it('should report error-severity problems for conflicting pointer ref names', async () => {
155+
const { problems } = await bundle({
156+
config: await createConfig({}),
157+
ref: path.join(
158+
__dirname,
159+
'fixtures/refs/openapi-with-external-refs-pointer-conflicting-names.yaml'
160+
),
161+
componentRenamingConflicts: 'error',
162+
});
163+
expect(problems).toHaveLength(1);
164+
expect(problems[0].severity).toBe('error');
165+
expect(problems[0].message).toEqual(
166+
`Two schemas are referenced with the same name but different content. Renamed User to User-2.`
167+
);
168+
});
169+
170+
it('should keep dotted JSON pointer schema keys and rename conflicting User schemas', async () => {
171+
const { bundle: res, problems } = await bundle({
172+
config: await createConfig({}),
173+
ref: path.join(
174+
__dirname,
175+
'fixtures/refs/openapi-bundle-external-schema-names-and-user-conflict.yaml'
176+
),
177+
});
178+
179+
expect(problems).toHaveLength(0);
180+
const schemas = (res.parsed as { components: { schemas: Record<string, unknown> } }).components
181+
.schemas;
182+
expect(schemas['my.org.User']).toBeDefined();
183+
expect(schemas['my.User']).toBeDefined();
184+
expect(res.parsed).toMatchSnapshot();
185+
});
186+
122187
it('should dereferenced correctly when used with dereference', async () => {
123188
const { bundle: res, problems } = await bundleDocument({
124189
externalRefResolver: new BaseResolver(),
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
components:
2+
parameters:
3+
User:
4+
name: test
5+
in: path
6+
description: test-A
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
components:
2+
parameters:
3+
User:
4+
name: test
5+
in: query
6+
description: test-B
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
components:
2+
schemas:
3+
my.org.User:
4+
type: object
5+
properties:
6+
orgId:
7+
type: string
8+
my.User:
9+
type: object
10+
properties:
11+
displayName:
12+
type: string
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
openapi: 3.0.0
2+
info:
3+
title: Test ref with dots in component names
4+
version: '1.0'
5+
description: Demo
6+
license:
7+
name: DEMO
8+
url: https://demo.com
9+
servers:
10+
- url: http://demo.com/api
11+
paths:
12+
/org-user:
13+
get:
14+
responses:
15+
'200':
16+
description: ok
17+
content:
18+
application/json:
19+
schema:
20+
$ref: external-ref-with-dots.yaml#/components/schemas/my.org.User
21+
post:
22+
responses:
23+
'200':
24+
description: ok
25+
content:
26+
application/json:
27+
schema:
28+
additionalProperties:
29+
$ref: external-ref-with-dots.yaml#/components/schemas/my.User
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
openapi: 3.1.0
2+
paths:
3+
/foo:
4+
put:
5+
parameters:
6+
- $ref: 'component-a.yaml#/components/parameters/User'
7+
get:
8+
parameters:
9+
- $ref: 'component-b.yaml#/components/parameters/User'

0 commit comments

Comments
 (0)