Skip to content
Open
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
101 changes: 101 additions & 0 deletions packages/cli/tests/cli/dev-media.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { describe, expect, it } from "vitest";
import { waitForDevServer } from "./testkit/dev-utils.js";
import { fixture, setupCLITests } from "./testkit/index.js";

describe("media in dev", () => {
const t = setupCLITests();

it("should upload public file and serve it", async () => {
await t.givenLoggedInWithProject(fixture("basic"));

const handle = await t.runLive("dev");
const url = await waitForDevServer(handle);

const form = new FormData();
form.append(
"file",
new Blob(["hello world"], { type: "text/plain" }),
"test.txt",
);

const uploadRes = await fetch(
`${url}/api/apps/${t.kit.api.appId}/integration-endpoints/Core/UploadFile`,
{ method: "POST", body: form },
);
expect(uploadRes.status).toBe(200);

const { file_url } = (await uploadRes.json()) as { file_url: string };
expect(file_url).toMatch(/\/media\/.+\.txt$/);

const fileRes = await fetch(file_url);
expect(fileRes.status).toBe(200);
expect(await fileRes.text()).toBe("hello world");

const result = await handle.stop();
t.expectResult(result).toSucceed();
});

it("should upload secret file and serve it with token", async () => {
await t.givenLoggedInWithProject(fixture("basic"));

const handle = await t.runLive("dev");
const url = await waitForDevServer(handle);

const form = new FormData();
form.append(
"file",
new Blob(["secret content"], { type: "text/plain" }),
"secret.txt",
);

const uploadRes = await fetch(
`${url}/api/apps/${t.kit.api.appId}/integration-endpoints/Core/UploadPrivateFile`,
{ method: "POST", body: form },
);
expect(uploadRes.status).toBe(200);

const { file_uri } = (await uploadRes.json()) as { file_uri: string };
expect(file_uri).toMatch(/\.txt$/);

// Get a signed URL for the private file
const signedUrlRes = await fetch(
`${url}/api/apps/${t.kit.api.appId}/integration-endpoints/Core/CreateFileSignedUrl`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ file_uri }),
},
);
expect(signedUrlRes.status).toBe(200);

const { signed_url } = (await signedUrlRes.json()) as {
signed_url: string;
};
expect(signed_url).toContain("/media/private/");
expect(signed_url).toContain("token=");

// Fetch with valid token succeeds
const fileRes = await fetch(signed_url);
expect(fileRes.status).toBe(200);
expect(await fileRes.text()).toBe("secret content");

// Fetch with wrong token returns 400
const badUrl = signed_url.replace(/([?&]token=)[^&]+/, "$1invalid");
const badRes = await fetch(badUrl);
expect(badRes.status).toBe(400);
const badBody = (await badRes.json()) as { error: string };
expect(badBody.error).toBe("InvalidJWT");

// Fetch with no token returns 401
const urlWithToken = new URL(signed_url);
urlWithToken.searchParams.delete("token");
const noTokenUrl = urlWithToken.toString();
const noTokenRes = await fetch(noTokenUrl);
expect(noTokenRes.status).toBe(401);
const noTokenBody = (await noTokenRes.json()) as { error: string };
expect(noTokenBody.error).toBe("Missing token");

const result = await handle.stop();
t.expectResult(result).toSucceed();
});
});
12 changes: 2 additions & 10 deletions packages/cli/tests/cli/dev.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { describe, it } from "vitest";
import { fixture, type RunLiveHandle, setupCLITests } from "./testkit/index.js";

const waitForDevServer = async (
runLiveHandle: RunLiveHandle,
): Promise<string> => {
const pattern = /Dev server is available at (http\S+)/;
await runLiveHandle.waitForOutput(pattern);
const match = runLiveHandle.stdout.join("").match(pattern)!;
return match[1];
};
import { waitForDevServer } from "./testkit/dev-utils.js";
import { fixture, setupCLITests } from "./testkit/index.js";

describe("dev command", () => {
const t = setupCLITests();
Expand Down
13 changes: 13 additions & 0 deletions packages/cli/tests/cli/testkit/dev-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { RunLiveHandle } from "./CLITestkit";

export const waitForDevServer = async (
runLiveHandle: RunLiveHandle,
): Promise<string> => {
const pattern = /Dev server is available at (http\S+)/;
await runLiveHandle.waitForOutput(pattern);
const match = runLiveHandle.stdout.join("").match(pattern);
if (!match) {
throw new Error(`Can't find dev server url`);
}
return match[1];
};
Loading