Validation: the dump validators refuse the nulls their shared types don't allow (a null title or note on creation, a null URL on edit); a playlist title of spaces is refused and titles are stored trimmed; usernames and emails are checked by the same USERNAME_RE and EMAIL_RE in shared/validation.ts on sign-up, on PATCH /api/users/me (which checked other limits) and in the sign-up form. Mentions are read by shared/mention.ts's mentionedUsernames, which skips code and URLs as Markdown shows them: https://mastodon.social/@bob or a `@bob` in code notified bob; the editor's suggestions derive their trigger from the same pattern instead of a copy. Following an unknown user is a 404 rather than a foreign-key 500, and following a private playlist a 404 rather than a 403 that confirmed it exists. `ws` and `emojibase` are reserved category slugs, since the server answers them before the app. GET /api/users/me no longer turns every error into a 500. Dead code goes: adminOnlyMiddleware, verifyEmailTransport, listUsers, deleteUser with disconnectUser and the force_logout message only it sent, PATCH /api/notifications/:id/read (with markOneRead), isSlugAvailable, the unreachable 500 in fetchComment, and the `if (!ctx.state.user)` checks behind authMiddleware. 214 backend and 627 frontend tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
import { get, PNG, stubNetwork } from "../helpers.ts";
|
|
import { assertEquals } from "@std/assert";
|
|
|
|
Deno.test("GET /api/proxy-image: rasters only, fetched once for everyone", async () => {
|
|
using net = stubNetwork((url) =>
|
|
url.pathname.endsWith(".svg")
|
|
? new Response("<svg/>", { headers: { "content-type": "image/svg+xml" } })
|
|
: new Response(PNG, { headers: { "content-type": "image/png" } })
|
|
);
|
|
const path = `/api/proxy-image?url=${
|
|
encodeURIComponent("https://cdn.example.com/a.png")
|
|
}`;
|
|
const first = await get(path);
|
|
assertEquals(first.status, 200);
|
|
assertEquals(first.headers.get("content-type"), "image/png");
|
|
assertEquals(first.bytes, PNG);
|
|
const second = await get(path);
|
|
assertEquals(second.bytes, PNG);
|
|
assertEquals(net.calls.length, 1);
|
|
|
|
const svg = await get(
|
|
`/api/proxy-image?url=${
|
|
encodeURIComponent("https://cdn.example.com/a.svg")
|
|
}`,
|
|
);
|
|
assertEquals(svg.status, 400);
|
|
});
|
|
|
|
Deno.test("GET /api/proxy-image: an error answer is never served nor cached", async () => {
|
|
let failing = true;
|
|
using net = stubNetwork(() =>
|
|
failing
|
|
? new Response(PNG, {
|
|
status: 503,
|
|
headers: { "content-type": "image/png" },
|
|
})
|
|
: new Response(PNG, { headers: { "content-type": "image/png" } })
|
|
);
|
|
const path = `/api/proxy-image?url=${
|
|
encodeURIComponent("https://cdn.example.com/flaky.png")
|
|
}`;
|
|
assertEquals((await get(path)).status, 400);
|
|
failing = false;
|
|
assertEquals((await get(path)).status, 200);
|
|
assertEquals(net.calls.length, 2);
|
|
});
|