Skip to content

Commit f5eeb16

Browse files
committed
feat: enhance AGENTS documentation with testing guidelines, add new OpenAPI 3.x and Swagger 2.0 test fixtures, and improve parameter handling in parser
1 parent a2c2ae1 commit f5eeb16

30 files changed

Lines changed: 1996 additions & 4 deletions

AGENTS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# AGENTS
22

3+
## Testing Guidelines
4+
5+
- **Specification benchmark**: Conduct unit testing based on OpenAPI 2.0 (Swagger 2.0) and OpenAPI 3.2 specification benchmarks. Use skills `openapi-specification-v2` and `openapi-specification-v3.2` when writing or validating tests and fixtures.
6+
- **Coverage**: Strive to cover all scenarios as much as possible—paths, operations, parameters, request/response, schema, security, and edge cases defined in the specs.
7+
- **Scope**: Focus unit tests on the following subpackages:
8+
- `packages/parser` — parsing and transforming OpenAPI/Swagger structures
9+
- `packages/transform` — spec conversions (e.g. Swagger 2 → 3, wpapi → Swagger 2)
10+
- **Failure handling**: If a single test fails, **prioritize fixing the source code** (implementation bugs, spec violations) rather than changing the test code to make the test pass.
11+
312
<skills_system priority="1">
413

514
## Available Skills

packages/parser/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
"transliteration": "catalog:runtime"
4040
},
4141
"devDependencies": {
42-
"openapi-specification-types": "catalog:openapi"
42+
"openapi-specification-types": "catalog:openapi",
43+
"vitest": "catalog:testing"
4344
},
4445
"publishConfig": {
4546
"exports": {

packages/parser/src/parses/common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { swagger2ToSwagger3 } from '@genapi/transform'
99
export function parseHeaderCommits(source: OpenAPISpecificationV2) {
1010
const comments = [
1111
`@title ${source.info.title}`,
12-
`@description ${source.info.description}`,
12+
source.info.description != null && source.info.description !== '' && `@description ${source.info.description}`,
1313
source.swagger && `@swagger ${source.swagger}`,
1414
`@version ${source.info.version}`,
1515
].filter(Boolean)

packages/parser/src/parses/parameter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export function parseParameterFiled(parameter: Parameter) {
2525
field.description = [field.description || '', enumsDesc].filter(Boolean)
2626
}
2727

28-
if (['formData', 'body', 'header', 'path', 'query'].includes(parameter.in))
28+
if (['formData', 'body', 'header', 'path', 'query', 'cookie', 'querystring'].includes(parameter.in))
2929
field.type = parseSchemaType(parameter as Parameters<typeof parseSchemaType>[0])
3030

3131
if (!field.description)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import type { OpenAPISpecificationV3 } from 'openapi-specification-types'
2+
3+
/**
4+
* OpenAPI 3.x spec: components.schemas, securitySchemes, tags, externalDocs.
5+
* Benchmark: OAS 3 - Components, Security Schemes, Tags.
6+
*/
7+
export const openapi3Components: OpenAPISpecificationV3 = {
8+
openapi: '3.0.0',
9+
info: { title: 'Components API', version: '1.0.0' },
10+
servers: [{ url: 'https://api.example.com/v1' }],
11+
paths: {
12+
'/pets': {
13+
get: {
14+
operationId: 'listPets',
15+
tags: ['pets'],
16+
security: [{ petstore_auth: ['read:pets'] }],
17+
responses: { 200: { description: 'OK', content: { 'application/json': { schema: { $ref: '#/components/schemas/PetList' } } } } },
18+
},
19+
},
20+
},
21+
components: {
22+
schemas: {
23+
Pet: {
24+
type: 'object',
25+
properties: { id: { type: 'integer' }, name: { type: 'string' } },
26+
},
27+
PetList: {
28+
type: 'array',
29+
items: { $ref: '#/components/schemas/Pet' },
30+
},
31+
},
32+
securitySchemes: {
33+
petstore_auth: {
34+
type: 'oauth2',
35+
flows: { implicit: { authorizationUrl: 'https://example.com/oauth', scopes: { 'read:pets': 'read pets' } } },
36+
},
37+
api_key: {
38+
type: 'apiKey',
39+
in: 'header',
40+
name: 'X-API-Key',
41+
},
42+
},
43+
},
44+
tags: [{ name: 'pets', description: 'Pet operations' }],
45+
externalDocs: { url: 'https://docs.example.com', description: 'API docs' },
46+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { OpenAPISpecificationV3 } from 'openapi-specification-types'
2+
3+
/**
4+
* Minimal OpenAPI 3.x spec: servers, paths, operation, responses with content.
5+
* Benchmark: OpenAPI 3.2 - Paths, Operation, Request Body, Responses with content.
6+
*/
7+
export const openapi3Minimal: OpenAPISpecificationV3 = {
8+
openapi: '3.0.0',
9+
info: { title: 'Minimal API', version: '1.0.0' },
10+
servers: [{ url: 'https://api.example.com/v1' }],
11+
paths: {
12+
'/pets': {
13+
get: {
14+
summary: 'List pets',
15+
operationId: 'listPets',
16+
responses: {
17+
200: {
18+
description: 'A list of pets.',
19+
content: {
20+
'application/json': {
21+
schema: { type: 'array', items: { type: 'object', properties: { id: { type: 'integer' }, name: { type: 'string' } } } },
22+
},
23+
},
24+
},
25+
},
26+
},
27+
},
28+
},
29+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { OpenAPISpecificationV3 } from 'openapi-specification-types'
2+
3+
/**
4+
* OpenAPI 3.x spec: parameters (path, query, header, cookie), style, explode.
5+
* Benchmark: OAS 3 - Parameter Object, in, style, schema, content.
6+
*/
7+
export const openapi3Parameters: OpenAPISpecificationV3 = {
8+
openapi: '3.0.0',
9+
info: { title: 'Parameters API', version: '1.0.0' },
10+
servers: [{ url: 'https://api.example.com/v1' }],
11+
paths: {
12+
'/pets/{petId}': {
13+
parameters: [
14+
{ name: 'petId', in: 'path', required: true, schema: { type: 'string' }, description: 'Pet ID' },
15+
],
16+
get: {
17+
operationId: 'getPet',
18+
parameters: [
19+
{ name: 'limit', in: 'query', schema: { type: 'integer', default: 10 } },
20+
{ name: 'tags', in: 'query', style: 'form', explode: true, schema: { type: 'array', items: { type: 'string' } } },
21+
{ name: 'X-Request-ID', in: 'header', schema: { type: 'string' } },
22+
{ name: 'session', in: 'cookie', schema: { type: 'string' } },
23+
],
24+
responses: { 200: { description: 'OK' } },
25+
},
26+
},
27+
},
28+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import type { OpenAPISpecificationV3 } from 'openapi-specification-types'
2+
3+
/**
4+
* OpenAPI 3.x spec: requestBody with application/json and multipart/form-data.
5+
* Benchmark: Request Body, Media Type, Encoding.
6+
*/
7+
export const openapi3RequestBody: OpenAPISpecificationV3 = {
8+
openapi: '3.0.0',
9+
info: { title: 'RequestBody API', version: '1.0.0' },
10+
servers: [{ url: 'https://api.example.com/v1' }],
11+
paths: {
12+
'/pets': {
13+
post: {
14+
operationId: 'createPet',
15+
requestBody: {
16+
description: 'Pet to create',
17+
content: {
18+
'application/json': {
19+
schema: {
20+
type: 'object',
21+
required: ['name'],
22+
properties: {
23+
name: { type: 'string' },
24+
tag: { type: 'string' },
25+
},
26+
},
27+
},
28+
},
29+
},
30+
responses: { 201: { description: 'Created' } },
31+
},
32+
},
33+
'/upload': {
34+
post: {
35+
operationId: 'uploadFile',
36+
requestBody: {
37+
content: {
38+
'multipart/form-data': {
39+
schema: {
40+
type: 'object',
41+
properties: {
42+
file: { type: 'string', format: 'binary' },
43+
name: { type: 'string' },
44+
},
45+
},
46+
},
47+
},
48+
},
49+
responses: { 200: { description: 'OK' } },
50+
},
51+
},
52+
},
53+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import type { OpenAPISpecificationV3 } from 'openapi-specification-types'
2+
3+
/**
4+
* OpenAPI 3.x spec: responses with default, multiple content types, headers.
5+
* Benchmark: OAS 3 - Responses Object, Response with content, headers, default.
6+
*/
7+
export const openapi3Responses: OpenAPISpecificationV3 = {
8+
openapi: '3.0.0',
9+
info: { title: 'Responses API', version: '1.0.0' },
10+
servers: [{ url: 'https://api.example.com/v1' }],
11+
paths: {
12+
'/pets': {
13+
get: {
14+
operationId: 'listPets',
15+
responses: {
16+
200: {
17+
description: 'Success',
18+
headers: {
19+
'X-Request-Id': { description: 'Request ID', schema: { type: 'string' } },
20+
},
21+
content: {
22+
'application/json': {
23+
schema: { type: 'array', items: { $ref: '#/components/schemas/Pet' } },
24+
},
25+
'text/plain': {
26+
schema: { type: 'string' },
27+
},
28+
},
29+
},
30+
default: {
31+
description: 'Error',
32+
content: {
33+
'application/json': {
34+
schema: { type: 'object', properties: { code: { type: 'integer' }, message: { type: 'string' } } },
35+
},
36+
},
37+
},
38+
},
39+
},
40+
},
41+
},
42+
components: {
43+
schemas: {
44+
Pet: {
45+
type: 'object',
46+
properties: { id: { type: 'integer' }, name: { type: 'string' } },
47+
},
48+
},
49+
},
50+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import type { OpenAPISpecificationV3 } from 'openapi-specification-types'
2+
3+
/**
4+
* OpenAPI 3.x spec: multiple servers, server variables (templated URL).
5+
* Benchmark: OAS 3 - Server Object, Server Variable.
6+
*/
7+
export const openapi3Servers: OpenAPISpecificationV3 = {
8+
openapi: '3.0.0',
9+
info: { title: 'Servers API', version: '1.0.0' },
10+
servers: [
11+
{ url: 'https://api.example.com/v1', description: 'Production' },
12+
{ url: 'https://staging.example.com/v1', description: 'Staging' },
13+
{
14+
url: 'https://{env}.example.com/{basePath}',
15+
description: 'Variable',
16+
variables: {
17+
env: { default: 'api' },
18+
basePath: { default: 'v1' },
19+
},
20+
},
21+
],
22+
paths: {
23+
'/ping': {
24+
get: {
25+
operationId: 'ping',
26+
responses: { 200: { description: 'OK' } },
27+
},
28+
},
29+
},
30+
}

0 commit comments

Comments
 (0)