Skip to content

Commit

Permalink
add endpoint summary field (#1373)
Browse files Browse the repository at this point in the history
  • Loading branch information
oben01 authored Apr 19, 2021
1 parent eda338d commit fadbf4c
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface SecurityHeader {
export interface Endpoint {
name: string;
description?: string;
summary?: string;
tags: string[];
method: HttpMethod;
path: string;
Expand Down
45 changes: 45 additions & 0 deletions lib/src/generators/openapi2/__snapshots__/openapi2.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,51 @@ exports[`OpenAPI 2 generator contract with version produces a versioned OpenAPI
}"
`;

exports[`OpenAPI 2 generator endpoint metadata contract with endpoint metadata description and summary 1`] = `
"{
\\"swagger\\": \\"2.0\\",
\\"info\\": {
\\"title\\": \\"contract\\",
\\"version\\": \\"0.0.0\\"
},
\\"consumes\\": [
\\"application/json\\"
],
\\"produces\\": [
\\"application/json\\"
],
\\"paths\\": {
\\"/users\\": {
\\"get\\": {
\\"description\\": \\"My description\\",
\\"summary\\": \\"My summary\\",
\\"operationId\\": \\"GetEndpoint\\",
\\"responses\\": {
\\"200\\": {
\\"description\\": \\"200 response\\",
\\"schema\\": {
\\"type\\": \\"object\\",
\\"properties\\": {
\\"id\\": {
\\"type\\": \\"string\\"
},
\\"name\\": {
\\"type\\": \\"string\\"
}
},
\\"required\\": [
\\"id\\",
\\"name\\"
]
}
}
}
}
}
}
}"
`;

exports[`OpenAPI 2 generator headers endpoint with request headers 1`] = `
"{
\\"swagger\\": \\"2.0\\",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { api, endpoint, response, String, body } from "@airtasker/spot";

@api({ name: "contract" })
class Contract {}

/**
* My description
*
* @summary
* My summary
*/
@endpoint({
method: "GET",
path: "/users"
})
class GetEndpoint {
@response({ status: 200 })
successResponse(@body body: { id: String; name: String }) {}
}
17 changes: 17 additions & 0 deletions lib/src/generators/openapi2/openapi2.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Contract } from "../../definitions";
import { parseContract } from "../../parsers/contract-parser";
import { createProjectFromExistingSourceFile } from "../../spec-helpers/helper";
import { generateOpenAPI2 } from "./openapi2";
import { generateOpenAPI3 } from "../openapi3";

describe("OpenAPI 2 generator", () => {
const spectral = new Spectral();
Expand Down Expand Up @@ -298,6 +299,22 @@ describe("OpenAPI 2 generator", () => {
expect(spectralResult).toHaveLength(0);
});
});
describe("endpoint metadata", () => {
test("contract with endpoint metadata description and summary", async () => {
const contract = generateContract("contract-with-endpoint-metadata.ts");
const result = generateOpenAPI2(contract);

expect(result.paths["/users"]).toMatchObject({
get: {
description: "My description",
summary: "My summary"
}
});
expect(JSON.stringify(result, null, 2)).toMatchSnapshot();
const spectralResult = await spectral.run(result);
expect(spectralResult).toHaveLength(0);
});
});
});

/**
Expand Down
1 change: 1 addition & 0 deletions lib/src/generators/openapi2/openapi2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ function endpointToOperationObject(
return {
tags: endpoint.tags.length > 0 ? endpoint.tags : undefined,
description: endpoint.description,
summary: endpoint.summary,
operationId: endpoint.name,
parameters:
endpointRequest &&
Expand Down
43 changes: 43 additions & 0 deletions lib/src/generators/openapi3/__snapshots__/openapi3.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,49 @@ exports[`OpenAPI 3 generator contract with one server OpenAPI 3 1`] = `
}"
`;

exports[`OpenAPI 3 generator endpoint metadata contract with endpoint metadata description and summary 1`] = `
"{
\\"openapi\\": \\"3.0.2\\",
\\"info\\": {
\\"title\\": \\"contract\\",
\\"version\\": \\"0.0.0\\"
},
\\"paths\\": {
\\"/users\\": {
\\"get\\": {
\\"description\\": \\"My description\\",
\\"summary\\": \\"My summary\\",
\\"operationId\\": \\"GetEndpoint\\",
\\"responses\\": {
\\"200\\": {
\\"description\\": \\"200 response\\",
\\"content\\": {
\\"application/json\\": {
\\"schema\\": {
\\"type\\": \\"object\\",
\\"properties\\": {
\\"id\\": {
\\"type\\": \\"string\\"
},
\\"name\\": {
\\"type\\": \\"string\\"
}
},
\\"required\\": [
\\"id\\",
\\"name\\"
]
}
}
}
}
}
}
}
}
}"
`;

exports[`OpenAPI 3 generator examples contract with examples parses correctly to an openapi specification 1`] = `
"{
\\"openapi\\": \\"3.0.2\\",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { api, endpoint, response, String, body } from "@airtasker/spot";

@api({ name: "contract" })
class Contract {}

/**
* My description
*
* @summary
* My summary
*/
@endpoint({
method: "GET",
path: "/users"
})
class GetEndpoint {
@response({ status: 200 })
successResponse(@body body: { id: String; name: String }) {}
}
17 changes: 17 additions & 0 deletions lib/src/generators/openapi3/openapi3.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,23 @@ describe("OpenAPI 3 generator", () => {
expect(spectralResult).toHaveLength(0);
});
});

describe("endpoint metadata", () => {
test("contract with endpoint metadata description and summary", async () => {
const contract = generateContract("contract-with-endpoint-metadata.ts");
const result = generateOpenAPI3(contract);

expect(result.paths["/users"]).toMatchObject({
get: {
description: "My description",
summary: "My summary"
}
});
expect(JSON.stringify(result, null, 2)).toMatchSnapshot();
const spectralResult = await spectral.run(result);
expect(spectralResult).toHaveLength(0);
});
});
});

/**
Expand Down
1 change: 1 addition & 0 deletions lib/src/generators/openapi3/openapi3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ function endpointToOperationObject(
return {
tags: endpoint.tags.length > 0 ? endpoint.tags : undefined,
description: endpoint.description,
summary: endpoint.summary,
operationId: endpoint.name,
parameters:
endpointRequest &&
Expand Down
12 changes: 12 additions & 0 deletions lib/src/parsers/__spec-examples__/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,15 @@ class EndpointWithDuplicateResponseStatus {
})
responseTwo() {}
}

/**
* My description
*
* @summary
* My summary
*/
@endpoint({
method: "GET",
path: "/path"
})
class MinimalEndpointWithSummaryClass {}
24 changes: 24 additions & 0 deletions lib/src/parsers/endpoint-parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ describe("endpoint parser", () => {
]
},
description: "endpoint description",
summary: undefined,
draft: false,
method: "POST",
name: "EndpointClass",
Expand Down Expand Up @@ -108,6 +109,7 @@ describe("endpoint parser", () => {
expect(result).toStrictEqual({
defaultResponse: undefined,
description: undefined,
summary: undefined,
draft: false,
method: "GET",
name: "MinimalEndpointClass",
Expand All @@ -128,6 +130,7 @@ describe("endpoint parser", () => {
expect(result).toStrictEqual({
defaultResponse: undefined,
description: undefined,
summary: undefined,
draft: true,
method: "GET",
name: "DraftEndpointClass",
Expand Down Expand Up @@ -207,4 +210,25 @@ describe("endpoint parser", () => {
)
).toThrowError("Expected to find decorator named 'endpoint'");
});

test("parses minimal @endpoint decorated class with summary field", () => {
const result = parseEndpoint(
exampleFile.getClassOrThrow("MinimalEndpointWithSummaryClass"),
typeTable,
lociTable
).unwrapOrThrow();

expect(result).toStrictEqual({
defaultResponse: undefined,
description: "My description",
summary: "My summary",
draft: false,
method: "GET",
name: "MinimalEndpointWithSummaryClass",
path: "/path",
request: undefined,
responses: [],
tags: []
});
});
});
11 changes: 10 additions & 1 deletion lib/src/parsers/endpoint-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,15 @@ export function parseEndpoint(
const tags = tagsResult.unwrap();

// Handle jsdoc
const description = getJsDoc(klass)?.getDescription().trim();
const jsDocNode = getJsDoc(klass);
const description = jsDocNode?.getDescription().trim();

// Handle summary
const summaryNode = jsDocNode
?.getTags()
.find(tag => tag.getTagName() === "summary");

const summary = summaryNode?.getComment();

// Handle draft
const draft = klass.getDecorator("draft") !== undefined;
Expand Down Expand Up @@ -131,6 +139,7 @@ export function parseEndpoint(
return ok({
name,
description,
summary,
tags,
method,
path,
Expand Down

0 comments on commit fadbf4c

Please sign in to comment.