Files
HealthLog/src/lib/withings/__tests__/sync.test.ts
T
Marc-André Bombeck fea1d1e0b5 chore: strip planning tags from comments and enable the rule
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.
2026-10-20 09:08:40 +02:00

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");
});
});