Skip to content

Commit 74b451c

Browse files
committed
Add E2E test
1 parent e53a42a commit 74b451c

File tree

11 files changed

+535
-8
lines changed

11 files changed

+535
-8
lines changed

packages/cli/cli/src/cli.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ async function tryRunCli(cliContext: CliContext) {
183183
});
184184
addGenerateJsonschemaCommand(cli, cliContext);
185185
addWriteDocsDefinitionCommand(cli, cliContext);
186+
addExportCommand(cli, cliContext);
186187

187188
// CLI V2 Sanctioned Commands
188189
addGetOrganizationCommand(cli, cliContext);

packages/cli/cli/src/commands/export/generateOpenAPIForWorkspaces.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,10 @@ export async function generateOpenAPIForWorkspaces({
2121
}) {
2222
await Promise.all(
2323
project.apiWorkspaces.map(async (workspace) => {
24-
if (!(workspace instanceof FernWorkspace)) {
25-
cliContext.failWithoutThrowing("Only Fern Definition APIs are supported for OpenAPI export.");
26-
return;
27-
}
28-
2924
await cliContext.runTaskForWorkspace(workspace, async (context) => {
30-
const ir = await generateIntermediateRepresentation({
31-
workspace,
25+
const fernWorkspace = await workspace.toFernWorkspace({ context });
26+
const ir = generateIntermediateRepresentation({
27+
workspace: fernWorkspace,
3228
audiences: { type: "all" },
3329
generationLanguage: undefined,
3430
keywords: undefined,
@@ -38,7 +34,7 @@ export async function generateOpenAPIForWorkspaces({
3834
version: undefined,
3935
packageName: undefined,
4036
context,
41-
sourceResolver: new SourceResolverImpl(context, workspace)
37+
sourceResolver: new SourceResolverImpl(context, fernWorkspace)
4238
});
4339
const openapi = convertIrToOpenApi({
4440
apiName: workspace.workspaceName ?? "api",
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`overrides > simple 1`] = `
4+
"openapi: 3.0.1
5+
info:
6+
title: api
7+
version: ''
8+
description: foo bar baz
9+
paths:
10+
/test/{rootPathParam}/movies:
11+
post:
12+
operationId: imdb_createMovie
13+
tags:
14+
- Imdb
15+
parameters:
16+
- name: rootPathParam
17+
in: path
18+
required: true
19+
schema:
20+
type: string
21+
responses:
22+
'200':
23+
description: ''
24+
content:
25+
application/json:
26+
schema:
27+
$ref: '#/components/schemas/MovieId'
28+
'400':
29+
description: ''
30+
content:
31+
application/json:
32+
schema:
33+
oneOf:
34+
- type: object
35+
properties:
36+
error:
37+
type: string
38+
enum:
39+
- BadRequestError
40+
security:
41+
- ApiKeyAuth: []
42+
requestBody:
43+
required: true
44+
content:
45+
application/json:
46+
schema:
47+
$ref: '#/components/schemas/CreateMovieRequest'
48+
/test/{rootPathParam}/movies/{movieId}:
49+
get:
50+
operationId: imdb_getMovie
51+
tags:
52+
- Imdb
53+
parameters:
54+
- name: rootPathParam
55+
in: path
56+
required: true
57+
schema:
58+
type: string
59+
- name: movieId
60+
in: path
61+
required: true
62+
schema:
63+
$ref: '#/components/schemas/MovieId'
64+
- name: movieName
65+
in: query
66+
required: true
67+
schema:
68+
type: array
69+
items:
70+
type: string
71+
responses:
72+
'200':
73+
description: ''
74+
content:
75+
application/json:
76+
schema:
77+
$ref: '#/components/schemas/Movie'
78+
'400':
79+
description: ''
80+
content:
81+
application/json:
82+
schema:
83+
oneOf:
84+
- type: object
85+
properties:
86+
error:
87+
type: string
88+
enum:
89+
- BadRequestError
90+
'404':
91+
description: ''
92+
content:
93+
application/json:
94+
schema:
95+
oneOf:
96+
- type: object
97+
properties:
98+
error:
99+
type: string
100+
enum:
101+
- NotFoundError
102+
content:
103+
type: string
104+
summary: Get Movie by Id
105+
delete:
106+
operationId: imdb_delete
107+
tags:
108+
- Imdb
109+
parameters:
110+
- name: rootPathParam
111+
in: path
112+
required: true
113+
schema:
114+
type: string
115+
- name: movieId
116+
in: path
117+
required: true
118+
schema:
119+
$ref: '#/components/schemas/MovieId'
120+
responses:
121+
'204':
122+
description: ''
123+
'400':
124+
description: ''
125+
content:
126+
application/json:
127+
schema:
128+
oneOf:
129+
- type: object
130+
properties:
131+
error:
132+
type: string
133+
enum:
134+
- BadRequestError
135+
components:
136+
schemas:
137+
UndiscriminatedUnion:
138+
title: UndiscriminatedUnion
139+
oneOf:
140+
- type: string
141+
- type: array
142+
items:
143+
type: string
144+
- type: integer
145+
- type: array
146+
items:
147+
type: array
148+
items:
149+
type: integer
150+
Director:
151+
title: Director
152+
type: object
153+
properties:
154+
name:
155+
type: string
156+
age:
157+
$ref: '#/components/schemas/Age'
158+
required:
159+
- name
160+
- age
161+
Age:
162+
title: Age
163+
type: integer
164+
LiteralString:
165+
title: LiteralString
166+
type: string
167+
const: hello
168+
CurrencyAmount:
169+
title: CurrencyAmount
170+
type: string
171+
MovieId:
172+
title: MovieId
173+
type: string
174+
ActorId:
175+
title: ActorId
176+
type: string
177+
Movie:
178+
title: Movie
179+
type: object
180+
properties:
181+
id:
182+
$ref: '#/components/schemas/MovieId'
183+
title:
184+
type: string
185+
rating:
186+
type: number
187+
format: double
188+
required:
189+
- id
190+
- title
191+
- rating
192+
CreateMovieRequest:
193+
title: CreateMovieRequest
194+
type: object
195+
properties:
196+
title:
197+
type: string
198+
ratings:
199+
type: array
200+
items:
201+
type: number
202+
format: double
203+
required:
204+
- title
205+
- ratings
206+
DirectorWrapper:
207+
title: DirectorWrapper
208+
type: object
209+
properties:
210+
director:
211+
$ref: '#/components/schemas/Director'
212+
required:
213+
- director
214+
EmptyObject:
215+
title: EmptyObject
216+
type: object
217+
properties: {}
218+
Person:
219+
title: Person
220+
oneOf:
221+
- type: object
222+
properties:
223+
type:
224+
type: string
225+
enum:
226+
- actor
227+
value:
228+
$ref: '#/components/schemas/ActorId'
229+
required:
230+
- type
231+
- type: object
232+
allOf:
233+
- type: object
234+
properties:
235+
type:
236+
type: string
237+
enum:
238+
- director
239+
- $ref: '#/components/schemas/Director'
240+
required:
241+
- type
242+
- type: object
243+
allOf:
244+
- type: object
245+
properties:
246+
type:
247+
type: string
248+
enum:
249+
- producer
250+
- $ref: '#/components/schemas/EmptyObject'
251+
required:
252+
- type
253+
- type: object
254+
allOf:
255+
- type: object
256+
properties:
257+
type:
258+
type: string
259+
enum:
260+
- cinematographer
261+
- $ref: '#/components/schemas/EmptyObject'
262+
required:
263+
- type
264+
RecursiveType:
265+
title: RecursiveType
266+
type: object
267+
properties:
268+
selfReferencing:
269+
type: array
270+
items:
271+
$ref: '#/components/schemas/RecursiveType'
272+
required:
273+
- selfReferencing
274+
allOf:
275+
- $ref: '#/components/schemas/CreateMovieRequest'
276+
securitySchemes:
277+
ApiKeyAuth:
278+
type: apiKey
279+
in: header
280+
name: X_API_KEY
281+
servers:
282+
- url: https://buildwithfern.com
283+
description: Production
284+
- url: https://staging.buildwithfern.com
285+
description: Staging
286+
"
287+
`;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { readFile } from "fs/promises";
2+
import path from "path";
3+
4+
import { AbsoluteFilePath } from "@fern-api/fs-utils";
5+
6+
import { runFernCli } from "../../utils/runFernCli";
7+
8+
const FIXTURES_DIR = path.join(__dirname, "fixtures");
9+
10+
describe("overrides", () => {
11+
itFixture("simple");
12+
});
13+
14+
function itFixture(fixtureName: string) {
15+
it(
16+
// eslint-disable-next-line jest/valid-title
17+
fixtureName,
18+
async () => {
19+
const fixturePath = path.join(FIXTURES_DIR, fixtureName);
20+
const outputPath = path.join(fixturePath, "openapi.yml");
21+
22+
await runFernCli(["export", outputPath], {
23+
cwd: fixturePath
24+
});
25+
26+
expect((await readFile(AbsoluteFilePath.of(outputPath))).toString()).toMatchSnapshot();
27+
},
28+
90_000
29+
);
30+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
openapi.yml
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
imports:
2+
commons: commons.yml
3+
name: my-api
4+
docs: foo bar baz
5+
auth: apiKey
6+
auth-schemes:
7+
apiKey:
8+
header: X_API_KEY
9+
name: apiKey
10+
headers:
11+
X-API-VERSION:
12+
name: apiVersion
13+
type: optional<string>
14+
error-discrimination:
15+
strategy: property
16+
property-name: error
17+
audiences:
18+
- test
19+
errors:
20+
- commons.BadRequestError
21+
default-environment: Production
22+
environments:
23+
Production: https://buildwithfern.com
24+
Staging: https://staging.buildwithfern.com
25+
base-path: /test/{rootPathParam}
26+
path-parameters:
27+
rootPathParam: string
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
types:
2+
UndiscriminatedUnion:
3+
discriminated: false
4+
union:
5+
- string
6+
- list<string>
7+
- integer
8+
- list<list<integer>>
9+
10+
errors:
11+
BadRequestError:
12+
status-code: 400

0 commit comments

Comments
 (0)