Skip to content

Commit b0f44f1

Browse files
committed
test: add cluster tests
1 parent 30a99b0 commit b0f44f1

File tree

13 files changed

+862
-2551
lines changed

13 files changed

+862
-2551
lines changed

.github/workflows/tests_daily.yaml renamed to .github/workflows/atlas_tests.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
---
2-
name: Code Health
2+
name: Atlas Tests
33
on:
4-
push:
5-
branches:
6-
- main
74
pull_request:
85
jobs:
96
run-tests-daily:

.github/workflows/code_health.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ jobs:
2020
- name: Run style check
2121
run: npm run check
2222

23+
check-generate:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
27+
- uses: actions/checkout@v4
28+
- uses: actions/setup-node@v4
29+
with:
30+
node-version-file: package.json
31+
cache: "npm"
32+
- name: Install dependencies
33+
run: npm ci
34+
- name: Run style check
35+
run: npm run generate
36+
2337
run-tests:
2438
strategy:
2539
matrix:

package-lock.json

Lines changed: 15 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
"ts-jest": "^29.3.1",
5454
"tsx": "^4.19.3",
5555
"typescript": "^5.8.2",
56-
"typescript-eslint": "^8.29.1"
56+
"typescript-eslint": "^8.29.1",
57+
"yaml": "^2.7.1"
5758
},
5859
"dependencies": {
5960
"@modelcontextprotocol/sdk": "^1.8.0",

scripts/apply.ts

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@ import fs from "fs/promises";
22
import { OpenAPIV3_1 } from "openapi-types";
33
import argv from "yargs-parser";
44

5-
function findParamFromRef(ref: string, openapi: OpenAPIV3_1.Document): OpenAPIV3_1.ParameterObject {
5+
function findObjectFromRef<T>(obj: T | OpenAPIV3_1.ReferenceObject, openapi: OpenAPIV3_1.Document): T {
6+
const ref = (obj as OpenAPIV3_1.ReferenceObject).$ref;
7+
if (ref === undefined) {
8+
return obj as T;
9+
}
610
const paramParts = ref.split("/");
711
paramParts.shift(); // Remove the first part which is always '#'
8-
let param: any = openapi; // eslint-disable-line @typescript-eslint/no-explicit-any
12+
let foundObj: any = openapi; // eslint-disable-line @typescript-eslint/no-explicit-any
913
while (true) {
1014
const part = paramParts.shift();
1115
if (!part) {
1216
break;
1317
}
14-
param = param[part];
18+
foundObj = foundObj[part];
1519
}
16-
return param;
20+
return foundObj as T;
1721
}
1822

1923
async function main() {
@@ -32,6 +36,7 @@ async function main() {
3236
operationId: string;
3337
requiredParams: boolean;
3438
tag: string;
39+
hasResponseBody: boolean;
3540
}[] = [];
3641

3742
const openapi = JSON.parse(specFile) as OpenAPIV3_1.Document;
@@ -44,13 +49,27 @@ async function main() {
4449
}
4550

4651
let requiredParams = !!operation.requestBody;
52+
let hasResponseBody = false;
53+
for(const code in operation.responses) {
54+
try {
55+
const httpCode = parseInt(code, 10);
56+
if (httpCode >= 200 && httpCode < 300) {
57+
const response = operation.responses[code];
58+
const responseObject = findObjectFromRef(response, openapi);
59+
if (responseObject.content) {
60+
for (const contentType in responseObject.content) {
61+
const content = responseObject.content[contentType];
62+
hasResponseBody = !!content.schema;
63+
}
64+
}
65+
}
66+
} catch {
67+
continue;
68+
}
69+
}
4770

4871
for (const param of operation.parameters || []) {
49-
const ref = (param as OpenAPIV3_1.ReferenceObject).$ref as string | undefined;
50-
let paramObject: OpenAPIV3_1.ParameterObject = param as OpenAPIV3_1.ParameterObject;
51-
if (ref) {
52-
paramObject = findParamFromRef(ref, openapi);
53-
}
72+
const paramObject = findObjectFromRef(param, openapi);
5473
if (paramObject.in === "path") {
5574
requiredParams = true;
5675
}
@@ -61,27 +80,41 @@ async function main() {
6180
method: method.toUpperCase(),
6281
operationId: operation.operationId || "",
6382
requiredParams,
83+
hasResponseBody,
6484
tag: operation.tags[0],
6585
});
6686
}
6787
}
6888

6989
const operationOutput = operations
7090
.map((operation) => {
71-
const { operationId, method, path, requiredParams } = operation;
91+
const { operationId, method, path, requiredParams, hasResponseBody } = operation;
7292
return `async ${operationId}(options${requiredParams ? "" : "?"}: FetchOptions<operations["${operationId}"]>) {
73-
const { data } = await this.client.${method}("${path}", options);
74-
return data;
75-
}
93+
${hasResponseBody ? `const { data } = ` : ``}await this.client.${method}("${path}", options);
94+
${hasResponseBody ? `return data;
95+
` : ``}}
7696
`;
7797
})
7898
.join("\n");
7999

80100
const templateFile = (await fs.readFile(file, "utf8")) as string;
81-
const output = templateFile.replace(
82-
/\/\/ DO NOT EDIT\. This is auto-generated code\.\n.*\/\/ DO NOT EDIT\. This is auto-generated code\./g,
83-
operationOutput
84-
);
101+
const templateLines = templateFile.split("\n");
102+
let outputLines: string[] = [];
103+
let addLines = true;
104+
for(const line of templateLines) {
105+
if (line.includes("DO NOT EDIT. This is auto-generated code.")) {
106+
addLines = !addLines;
107+
outputLines.push(line);
108+
if (!addLines) {
109+
outputLines.push(operationOutput);
110+
}
111+
continue;
112+
}
113+
if (addLines) {
114+
outputLines.push(line);
115+
}
116+
}
117+
const output = outputLines.join("\n");
85118

86119
await fs.writeFile(file, output, "utf8");
87120
}

scripts/filter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ function filterOpenapi(openapi: OpenAPIV3_1.Document): OpenAPIV3_1.Document {
2424
"listClusters",
2525
"getCluster",
2626
"createCluster",
27+
"deleteCluster",
2728
"listClustersForAllProjects",
2829
"createDatabaseUser",
2930
"listDatabaseUsers",

scripts/generate.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
set -Eeou pipefail
44

55
curl -Lo ./scripts/spec.json https://github.com/mongodb/openapi/raw/refs/heads/main/openapi/v2/openapi-2025-03-12.json
6-
tsx ./scripts/filter.ts > ./scripts/filteredSpec.json < ./scripts/spec.json
6+
tsx --debug-port 5858 ./scripts/filter.ts > ./scripts/filteredSpec.json < ./scripts/spec.json
77
redocly bundle --ext json --remove-unused-components ./scripts/filteredSpec.json --output ./scripts/bundledSpec.json
88
openapi-typescript ./scripts/bundledSpec.json --root-types-no-schema-prefix --root-types --output ./src/common/atlas/openapi.d.ts
99
tsx ./scripts/apply.ts --spec ./scripts/bundledSpec.json --file ./src/common/atlas/apiClient.ts

src/common/atlas/apiClient.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ export class ApiClient {
157157
return data;
158158
}
159159

160+
async deleteCluster(options: FetchOptions<operations["deleteCluster"]>) {
161+
await this.client.DELETE("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
162+
}
163+
160164
async getCluster(options: FetchOptions<operations["getCluster"]>) {
161165
const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options);
162166
return data;
@@ -171,5 +175,6 @@ export class ApiClient {
171175
const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/databaseUsers", options);
172176
return data;
173177
}
178+
174179
// DO NOT EDIT. This is auto-generated code.
175180
}

0 commit comments

Comments
 (0)