Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

draft: integration tests written in ts #4626

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions backend/tests/api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Api integration tests

You'll need deno to be installed and a windmill api endpoint.

By default the tests use the local environment endpoint <http://localhost:8000>. You can override it using `BASE_URL` environment variable.

By default the api authentication uses default local env user credentials. You can override api token using `WM_TOKEN` environment variable.

## Running the api tests

`deno test --allow-env --allow-net`
9 changes: 9 additions & 0 deletions backend/tests/api/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"tasks": {
"dev": "deno run --watch main.ts",
"test": "deno test --allow-env --allow-net"
},
"imports": {
"@std/assert": "jsr:@std/assert@1"
}
}
40 changes: 40 additions & 0 deletions backend/tests/api/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 80 additions & 0 deletions backend/tests/api/main_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

import { assertEquals } from "jsr:@std/assert";
import type { FlowPreview } from "../../../cli/gen/index.ts";
import * as api from "../../../cli/gen/index.ts";
import { awaitJobCompletion, setup } from "./utils.ts";

const flowPreview: FlowPreview = {
"args": {
"a": 4,
"b": 9
},
"value": {
"modules": [
{
"id": "a",
"value": {
"type": "rawscript",
"content": "// import * as wmill from \"windmill-client\"\n\nexport async function main(a: number, b : number) {\n return a + b\n}\n",
"language": "bun",
"input_transforms": {
"a": {
"type": "javascript",
"expr": "flow_input.a"
},
"b": {
"type": "javascript",
"expr": "flow_input.b"
}
},
"tag": ""
}
},
{
"id": "b",
"value": {
"type": "rawscript",
"content": "// import * as wmill from \"windmill-client\"\n\nexport async function main(n: number) {\n return n / 2.0\n}\n",
"language": "bun",
"input_transforms": {
"n": {
"type": "javascript",
"expr": "results.a"
}
},
"tag": ""
}
}
]
},
"path": "u/admin/beauteous_flow"
};

Deno.test("Run a flow preview and check its completion", async () => {
const { workspace } = await setup()

const id = await api.runFlowPreview({
workspace,
requestBody: flowPreview
});

const result = await awaitJobCompletion({ id, workspace, timeoutMs: 2000 });
assertEquals(result.result, 6.5);
assertEquals(result.canceled, false);
assertEquals(result.success, true);

});

Deno.test("Run a flow preview - Immediately cancel and check cancellation status", async () => {
const { workspace } = await setup()

const id = await api.runFlowPreview({
workspace,
requestBody: flowPreview
});

await api.cancelQueuedJob({ id, workspace, requestBody: { reason: "test cancellation"}});
const result = await awaitJobCompletion({ id, workspace, timeoutMs: 200});
assertEquals(result.canceled, true);
assertEquals(result.success, false);
});
51 changes: 51 additions & 0 deletions backend/tests/api/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { OpenAPI, createWorkspace, getJob, login } from "../../../cli/gen/index.ts";

// Setup method for each api test
export async function setup() {
await generateApiToken()
const workspace = await genTestWorkspace();

return { workspace }
}

async function generateApiToken() {
// if WM_TOKEN env variable not set
if (!OpenAPI.TOKEN) {
const email = Deno.env.get("LOGIN_WM_EMAIL") || "[email protected]";
const password = Deno.env.get("LOGIN_WM_PASSWORD") || "changeme";
const token = await login({ requestBody: { email, password } });
OpenAPI.TOKEN = token;
}

}

/**
* Ensure a workspace named "api-tests" is created
*/
async function genTestWorkspace() {
const id = "api-tests"

await createWorkspace({ requestBody: { id, name: id}}).catch(()=> null)

return id
}

/**
*
* @returns The job result
*/
export async function awaitJobCompletion(data: { workspace: string, id: string, timeoutMs: number }) {
const start = Date.now();
while (true) {
const result = await getJob(data).catch(()=> null);


if (!!result && result.type === "CompletedJob") {
return result;
}

if ((Date.now() - start) > data.timeoutMs) {
throw new Error("Job did not finish before the specified timeout: " + data.timeoutMs)
}
}
}
Loading