Skip to content

Commit ab4d5bc

Browse files
committed
✨ feat(openapi): enhance specPath handling for absolute and relative URLs in OpenAPI integration tests
1 parent 59a142b commit ab4d5bc

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

src/index.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,25 @@ export const openapi = <
3838
...documentation.info
3939
}
4040

41-
const relativePath = specPath.startsWith('/') ? specPath.slice(1) : specPath
41+
// Determine the correct URL for the OpenAPI spec
42+
// Use absolute path to avoid browser URL resolution issues when paths have complex hierarchies
43+
const getSpecUrl = () => {
44+
if (!specPath.startsWith('/')) {
45+
// Already relative
46+
return specPath
47+
}
48+
49+
// For default case where specPath follows the pattern path + '/json', use relative path
50+
const defaultSpecPath = `${path}/json`
51+
if (specPath === defaultSpecPath) {
52+
return specPath.startsWith('/') ? specPath.slice(1) : specPath
53+
}
54+
55+
// For custom specPath, use absolute path to prevent browser URL resolution issues
56+
return specPath
57+
}
58+
59+
const relativePath = getSpecUrl()
4260

4361
let totalRoutes = 0
4462
let cachedSchema: OpenAPIV3.Document | undefined

test/index.test.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { Elysia, t } from 'elysia'
21
import SwaggerParser from '@apidevtools/swagger-parser'
2+
import { Elysia, t } from 'elysia'
33
import { openapi } from '../src'
44

5-
import { describe, expect, it } from 'bun:test'
65
import { fail } from 'assert'
6+
import { describe, expect, it } from 'bun:test'
77

88
const req = (path: string) => new Request(`http://localhost${path}`)
99

@@ -272,4 +272,44 @@ describe('Swagger', () => {
272272
const response = await res.json()
273273
expect(Object.keys(response.paths['/all'])).toBeArrayOfSize(8)
274274
})
275+
276+
it('should use absolute path for custom specPath to prevent path duplication', async () => {
277+
const app = new Elysia().use(
278+
openapi({
279+
path: '/api/v1/docs',
280+
specPath: '/api/v1/openapi.json'
281+
})
282+
)
283+
284+
await app.modules
285+
286+
const res = await app.handle(req('/api/v1/docs')).then((x) => x.text())
287+
288+
// The data-url should be the absolute path to prevent duplication
289+
expect(res.includes('data-url="/api/v1/openapi.json"')).toBe(true)
290+
291+
// Ensure the spec endpoint works
292+
const specRes = await app.handle(req('/api/v1/openapi.json'))
293+
expect(specRes.status).toBe(200)
294+
})
295+
296+
it('should use relative path for default specPath pattern', async () => {
297+
const app = new Elysia().use(
298+
openapi({
299+
path: '/api/docs'
300+
// specPath defaults to '/api/docs/json'
301+
})
302+
)
303+
304+
await app.modules
305+
306+
const res = await app.handle(req('/api/docs')).then((x) => x.text())
307+
308+
// The data-url should be relative for default pattern
309+
expect(res.includes('data-url="api/docs/json"')).toBe(true)
310+
311+
// Ensure the spec endpoint works
312+
const specRes = await app.handle(req('/api/docs/json'))
313+
expect(specRes.status).toBe(200)
314+
})
275315
})

0 commit comments

Comments
 (0)