Files
kunthawat 2d1be52177 Emdash source with visual editor image upload fix
Fixes:
1. media.ts: wrap placeholder generation in try-catch
2. toolbar.ts: check r.ok, display error message in popover
2026-05-03 10:44:54 +07:00

171 lines
6.6 KiB
TypeScript

import { afterEach, beforeEach, describe, it, expect } from "vitest";
import {
getPublicOrigin,
getPublicUrl,
getEnvAllowedOrigins,
_resetEnvCache,
} from "../../../src/api/public-url.js";
import type { EmDashConfig } from "../../../src/astro/integration/runtime.js";
// Snapshot env vars we'll mutate, and restore after every test.
const origEmdashSiteUrl = process.env.EMDASH_SITE_URL;
const origSiteUrl = process.env.SITE_URL;
const origAllowedOrigins = process.env.EMDASH_ALLOWED_ORIGINS;
afterEach(() => {
_resetEnvCache();
// Restore original env state (delete if originally absent)
if (origEmdashSiteUrl === undefined) delete process.env.EMDASH_SITE_URL;
else process.env.EMDASH_SITE_URL = origEmdashSiteUrl;
if (origSiteUrl === undefined) delete process.env.SITE_URL;
else process.env.SITE_URL = origSiteUrl;
if (origAllowedOrigins === undefined) delete process.env.EMDASH_ALLOWED_ORIGINS;
else process.env.EMDASH_ALLOWED_ORIGINS = origAllowedOrigins;
});
// Ensure clean state before every test (no cache, no test env vars).
beforeEach(() => {
_resetEnvCache();
delete process.env.EMDASH_SITE_URL;
delete process.env.SITE_URL;
delete process.env.EMDASH_ALLOWED_ORIGINS;
});
describe("getPublicOrigin()", () => {
it("returns config.siteUrl when set", () => {
const url = new URL("http://localhost:4321/admin");
const config: EmDashConfig = { siteUrl: "https://mysite.example.com" };
expect(getPublicOrigin(url, config)).toBe("https://mysite.example.com");
});
it("returns url.origin when config has no siteUrl", () => {
const url = new URL("http://localhost:4321/admin");
const config: EmDashConfig = {};
expect(getPublicOrigin(url, config)).toBe("http://localhost:4321");
});
it("returns url.origin when config is undefined", () => {
const url = new URL("https://example.com:8443/setup");
expect(getPublicOrigin(url)).toBe("https://example.com:8443");
});
it("returns url.origin when config.siteUrl is undefined", () => {
const url = new URL("http://127.0.0.1:4321/api");
expect(getPublicOrigin(url, { siteUrl: undefined })).toBe("http://127.0.0.1:4321");
});
it("does not return empty string siteUrl (falsy)", () => {
const url = new URL("http://localhost:4321/x");
// Empty string should fall through to url.origin
expect(getPublicOrigin(url, { siteUrl: "" })).toBe("http://localhost:4321");
});
});
describe("getPublicOrigin() env var fallback", () => {
it("falls back to EMDASH_SITE_URL when config has no siteUrl", () => {
process.env.EMDASH_SITE_URL = "https://env.example.com";
const url = new URL("http://localhost:4321/x");
expect(getPublicOrigin(url, {})).toBe("https://env.example.com");
});
it("falls back to SITE_URL when EMDASH_SITE_URL is absent", () => {
process.env.SITE_URL = "https://site-url.example.com";
const url = new URL("http://localhost:4321/x");
expect(getPublicOrigin(url, {})).toBe("https://site-url.example.com");
});
it("prefers EMDASH_SITE_URL over SITE_URL", () => {
process.env.EMDASH_SITE_URL = "https://emdash.example.com";
process.env.SITE_URL = "https://site.example.com";
const url = new URL("http://localhost:4321/x");
expect(getPublicOrigin(url, {})).toBe("https://emdash.example.com");
});
it("normalizes env var to origin (strips path)", () => {
process.env.EMDASH_SITE_URL = "https://env.example.com/some/path";
const url = new URL("http://localhost:4321/x");
expect(getPublicOrigin(url, {})).toBe("https://env.example.com");
});
it("falls through to url.origin when env var is invalid URL", () => {
process.env.EMDASH_SITE_URL = "not-a-url";
const url = new URL("http://localhost:4321/x");
expect(getPublicOrigin(url, {})).toBe("http://localhost:4321");
});
it("config.siteUrl takes precedence over env var", () => {
process.env.EMDASH_SITE_URL = "https://env.example.com";
const url = new URL("http://localhost:4321/x");
const config: EmDashConfig = { siteUrl: "https://config.example.com" };
expect(getPublicOrigin(url, config)).toBe("https://config.example.com");
});
it("cache is invalidated by _resetEnvCache()", () => {
process.env.EMDASH_SITE_URL = "https://first.example.com";
const url = new URL("http://localhost:4321/x");
expect(getPublicOrigin(url, {})).toBe("https://first.example.com");
_resetEnvCache();
process.env.EMDASH_SITE_URL = "https://second.example.com";
expect(getPublicOrigin(url, {})).toBe("https://second.example.com");
});
});
describe("getEnvAllowedOrigins()", () => {
it("returns [] when EMDASH_ALLOWED_ORIGINS is unset", () => {
expect(getEnvAllowedOrigins()).toEqual([]);
});
it("parses a comma-separated list into origins", () => {
process.env.EMDASH_ALLOWED_ORIGINS = "https://example.com,https://preview.example.com";
expect(getEnvAllowedOrigins()).toEqual(["https://example.com", "https://preview.example.com"]);
});
it("trims whitespace around each entry", () => {
process.env.EMDASH_ALLOWED_ORIGINS = " https://example.com , https://preview.example.com ";
expect(getEnvAllowedOrigins()).toEqual(["https://example.com", "https://preview.example.com"]);
});
it("normalizes each entry to its origin (strips path/query)", () => {
process.env.EMDASH_ALLOWED_ORIGINS = "https://example.com/x?y=1";
expect(getEnvAllowedOrigins()).toEqual(["https://example.com"]);
});
it("throws on entries with non-http(s) protocols", () => {
process.env.EMDASH_ALLOWED_ORIGINS = "file:///etc/passwd,https://example.com";
expect(() => getEnvAllowedOrigins()).toThrow(/EMDASH_ALLOWED_ORIGINS.*must be http or https/);
});
it("throws on unparseable entries", () => {
process.env.EMDASH_ALLOWED_ORIGINS = "not-a-url,https://example.com";
expect(() => getEnvAllowedOrigins()).toThrow(/EMDASH_ALLOWED_ORIGINS.*invalid URL/);
});
it("cache is invalidated by _resetEnvCache()", () => {
process.env.EMDASH_ALLOWED_ORIGINS = "https://first.example.com";
expect(getEnvAllowedOrigins()).toEqual(["https://first.example.com"]);
_resetEnvCache();
process.env.EMDASH_ALLOWED_ORIGINS = "https://second.example.com";
expect(getEnvAllowedOrigins()).toEqual(["https://second.example.com"]);
});
});
describe("getPublicUrl()", () => {
it("builds full URL from siteUrl + path", () => {
const url = new URL("http://localhost:4321/x");
const config: EmDashConfig = { siteUrl: "https://mysite.example.com" };
expect(getPublicUrl(url, config, "/_emdash/admin/login")).toBe(
"https://mysite.example.com/_emdash/admin/login",
);
});
it("builds full URL from request origin when no siteUrl", () => {
const url = new URL("http://localhost:4321/x");
expect(getPublicUrl(url, undefined, "/_emdash/admin/login")).toBe(
"http://localhost:4321/_emdash/admin/login",
);
});
});