mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 22:32:04 +00:00
Output of `node scripts/strip-planning-tags.mjs --write`: 3,157 comment lines in 1,308 files lose the work-item identifier at their head. Release versions and issue references stay; nothing outside comment text changes, which the script checks per file against a comment-free printout. healthlog/no-planning-tags is enabled at error level with this commit, so the tree it lands on is clean.
75 lines
2.8 KiB
TypeScript
75 lines
2.8 KiB
TypeScript
import { afterEach, describe, expect, it } from "vitest";
|
|
import {
|
|
getWithingsWebhookCallbackUrl,
|
|
WITHINGS_INCREMENTAL_OVERLAP_MS,
|
|
} from "../sync";
|
|
|
|
/**
|
|
* The incremental overlap must stay comfortably wider than the old
|
|
* 60s so a backdated Withings reading landing just before the next cycle's
|
|
* `now()` is not missed (compounded by `lastSyncedAt` advancing on a healthy
|
|
* 200-with-0 cycle). The upserts are idempotent, so a wider overlap is safe.
|
|
*/
|
|
describe("WITHINGS_INCREMENTAL_OVERLAP_MS", () => {
|
|
it("is at least a few minutes (not the old 60s)", () => {
|
|
expect(WITHINGS_INCREMENTAL_OVERLAP_MS).toBeGreaterThanOrEqual(5 * 60_000);
|
|
expect(WITHINGS_INCREMENTAL_OVERLAP_MS).toBeGreaterThan(60_000);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* v1.4.25 — Withings webhook callback URL must put the shared
|
|
* secret in the PATH (not the `?secret=` query parameter) so that the
|
|
* value never lands in a reverse-proxy `query_string` access-log
|
|
* column. Withings preserves the full URL on every notification, so
|
|
* the format chosen at subscribe time is what every inbound delivery
|
|
* carries thereafter.
|
|
*/
|
|
describe("getWithingsWebhookCallbackUrl", () => {
|
|
const ORIGINAL_BASE = process.env.NEXT_PUBLIC_APP_URL;
|
|
const ORIGINAL_SECRET = process.env.WITHINGS_WEBHOOK_SECRET;
|
|
|
|
afterEach(() => {
|
|
if (ORIGINAL_BASE === undefined) delete process.env.NEXT_PUBLIC_APP_URL;
|
|
else process.env.NEXT_PUBLIC_APP_URL = ORIGINAL_BASE;
|
|
if (ORIGINAL_SECRET === undefined)
|
|
delete process.env.WITHINGS_WEBHOOK_SECRET;
|
|
else process.env.WITHINGS_WEBHOOK_SECRET = ORIGINAL_SECRET;
|
|
});
|
|
|
|
it("encodes the secret as the final path segment, not as ?secret=", () => {
|
|
process.env.NEXT_PUBLIC_APP_URL = "https://healthlog.example.com";
|
|
process.env.WITHINGS_WEBHOOK_SECRET = "super-secret-value";
|
|
|
|
const url = getWithingsWebhookCallbackUrl();
|
|
|
|
expect(url).toBe(
|
|
"https://healthlog.example.com/api/withings/webhook/super-secret-value",
|
|
);
|
|
expect(url).not.toContain("?secret=");
|
|
expect(url).not.toContain("?");
|
|
});
|
|
|
|
it("URL-encodes path-unsafe characters in the secret", () => {
|
|
process.env.NEXT_PUBLIC_APP_URL = "https://healthlog.example.com";
|
|
process.env.WITHINGS_WEBHOOK_SECRET = "a/b c?d";
|
|
|
|
const url = getWithingsWebhookCallbackUrl();
|
|
|
|
// `/`, ` `, and `?` would all break the path semantics if injected
|
|
// raw; encodeURIComponent yields `a%2Fb%20c%3Fd`.
|
|
expect(url).toBe(
|
|
"https://healthlog.example.com/api/withings/webhook/a%2Fb%20c%3Fd",
|
|
);
|
|
});
|
|
|
|
it("falls back to the bare legacy URL when WITHINGS_WEBHOOK_SECRET is unset", () => {
|
|
process.env.NEXT_PUBLIC_APP_URL = "https://healthlog.example.com";
|
|
delete process.env.WITHINGS_WEBHOOK_SECRET;
|
|
|
|
const url = getWithingsWebhookCallbackUrl();
|
|
|
|
expect(url).toBe("https://healthlog.example.com/api/withings/webhook");
|
|
});
|
|
});
|