mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
- Atomic CreateUserWithInvite prevents invite burn on failed registration - Channel search fails closed on channel-type and override lookup errors - Malformed FTS input returns 400 instead of 500 - Search rate limiting uses own namespace, respects trusted proxy IPs - Login lockout keyed by forwarded client IP behind reverse proxy - Trusted same-server OG previews re-enabled with self-signed cert support - Normalized host matching for embeds/attachments - Regression tests for all changes (auth, channel, embeds)
110 lines
3.2 KiB
TypeScript
110 lines
3.2 KiB
TypeScript
import {
|
|
afterEach,
|
|
beforeEach,
|
|
describe,
|
|
expect,
|
|
it,
|
|
vi,
|
|
} from "vitest";
|
|
|
|
const { fetchMock } = vi.hoisted(() => ({
|
|
fetchMock: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@tauri-apps/plugin-http", () => ({
|
|
fetch: fetchMock,
|
|
}));
|
|
|
|
import { renderGenericLinkPreview } from "../../src/components/message-list/embeds";
|
|
import { setServerHost } from "../../src/components/message-list/attachments";
|
|
|
|
function mockHtmlResponse(html: string) {
|
|
return {
|
|
ok: true,
|
|
headers: {
|
|
get(name: string) {
|
|
return name.toLowerCase() === "content-type" ? "text/html; charset=utf-8" : null;
|
|
},
|
|
},
|
|
text: vi.fn().mockResolvedValue(html),
|
|
};
|
|
}
|
|
|
|
describe("renderGenericLinkPreview", () => {
|
|
beforeEach(() => {
|
|
document.body.innerHTML = "";
|
|
fetchMock.mockReset();
|
|
setServerHost("example.com");
|
|
});
|
|
|
|
afterEach(() => {
|
|
document.body.innerHTML = "";
|
|
});
|
|
|
|
it("fetches OG metadata for public domains that begin with fd", async () => {
|
|
fetchMock.mockResolvedValue(mockHtmlResponse("<html><head><title>F-Droid</title></head></html>"));
|
|
|
|
const card = renderGenericLinkPreview("https://fdroid.org/packages");
|
|
document.body.appendChild(card);
|
|
|
|
await vi.waitFor(() => {
|
|
expect(fetchMock).toHaveBeenCalledWith(
|
|
"https://fdroid.org/packages",
|
|
expect.objectContaining({
|
|
headers: expect.objectContaining({
|
|
"User-Agent": expect.stringContaining("facebookexternalhit"),
|
|
}),
|
|
}),
|
|
);
|
|
});
|
|
|
|
await vi.waitFor(() => {
|
|
expect(card.querySelector(".msg-embed-link-title")?.textContent).toBe("F-Droid");
|
|
});
|
|
});
|
|
|
|
it("blocks previews for private IPv6 literals", async () => {
|
|
for (const url of ["https://[fd00::1]/", "https://[fe80::1]/", "https://[::ffff:127.0.0.1]/"]) {
|
|
document.body.innerHTML = "";
|
|
const card = renderGenericLinkPreview(url);
|
|
document.body.appendChild(card);
|
|
await Promise.resolve();
|
|
expect(card.querySelector(".msg-embed-link-title")?.textContent).toBeTruthy();
|
|
}
|
|
|
|
expect(fetchMock).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("blocks previews for loopback IPv4 literals beyond 127.0.0.1", async () => {
|
|
const card = renderGenericLinkPreview("https://127.0.0.2/internal");
|
|
document.body.appendChild(card);
|
|
|
|
await Promise.resolve();
|
|
|
|
expect(fetchMock).not.toHaveBeenCalled();
|
|
expect(card.querySelector(".msg-embed-link-title")?.textContent).toBe("127.0.0.2");
|
|
});
|
|
|
|
it("allows previews for the configured OwnCord server even on private hosts", async () => {
|
|
setServerHost("LOCALHOST:8080");
|
|
fetchMock.mockResolvedValue(mockHtmlResponse("<html><head><title>OwnCord Local</title></head></html>"));
|
|
|
|
const card = renderGenericLinkPreview("https://localhost:8080/docs");
|
|
document.body.appendChild(card);
|
|
|
|
await vi.waitFor(() => {
|
|
expect(fetchMock).toHaveBeenCalledWith(
|
|
"https://localhost:8080/docs",
|
|
expect.objectContaining({
|
|
headers: expect.objectContaining({
|
|
"User-Agent": expect.stringContaining("facebookexternalhit"),
|
|
}),
|
|
}),
|
|
);
|
|
});
|
|
|
|
await vi.waitFor(() => {
|
|
expect(card.querySelector(".msg-embed-link-title")?.textContent).toBe("OwnCord Local");
|
|
});
|
|
});
|
|
}); |