CI / Build & Quality Checks (pull_request) Successful in 1m50s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 13s
CI / Playwright smoke (e2e) (pull_request) Successful in 12m29s
#279: Room Settings → Soundboard said clips are "inherited by every room under this space" for plain rooms too; the wording now follows room.isSpaceRoom(). The Push to Deafen description only mentions Escape while rebinding. "can pin a messages" → "can pin a message". #280: the tracking stripper removed Reddit's context=, which is what makes a comment permalink show its parent comments. Only share_id and rdt are stripped now. Fixes #279 Fixes #280 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
119 lines
4.3 KiB
TypeScript
119 lines
4.3 KiB
TypeScript
import { describe, it } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {
|
|
stripTrackingParams,
|
|
stripTrackingParamsInHtml,
|
|
stripTrackingParamsInText,
|
|
} from './urlTracking';
|
|
|
|
describe('stripTrackingParams', () => {
|
|
it('removes utm_* and known global params, keeps the rest', () => {
|
|
const out = stripTrackingParams(
|
|
'https://example.com/a?utm_source=x&utm_medium=y&fbclid=abc&page=2&gclid=1',
|
|
);
|
|
assert.equal(out, 'https://example.com/a?page=2');
|
|
});
|
|
|
|
it('drops the dangling ? when every param was tracking', () => {
|
|
assert.equal(
|
|
stripTrackingParams('https://example.com/a?utm_source=x'),
|
|
'https://example.com/a',
|
|
);
|
|
});
|
|
|
|
it('returns the identical string when nothing changed', () => {
|
|
const url = 'https://example.com/a?page=2#frag';
|
|
assert.equal(stripTrackingParams(url), url);
|
|
});
|
|
|
|
it('preserves the fragment', () => {
|
|
assert.equal(
|
|
stripTrackingParams('https://example.com/a?utm_source=x#section-3'),
|
|
'https://example.com/a#section-3',
|
|
);
|
|
});
|
|
|
|
it('applies host rules only on that host', () => {
|
|
assert.equal(
|
|
stripTrackingParams('https://youtu.be/dQw4w9WgXcQ?si=abc123&t=42'),
|
|
'https://youtu.be/dQw4w9WgXcQ?t=42',
|
|
);
|
|
assert.equal(
|
|
stripTrackingParams('https://www.youtube.com/watch?v=dQw4w9WgXcQ&feature=share&si=x'),
|
|
'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
|
);
|
|
// `si` is not tracking elsewhere.
|
|
const other = 'https://example.com/?si=keep';
|
|
assert.equal(stripTrackingParams(other), other);
|
|
});
|
|
|
|
it('strips amazon affiliate/telemetry params and the /ref= path segment but keeps variant selectors', () => {
|
|
assert.equal(
|
|
stripTrackingParams(
|
|
'https://www.amazon.com/dp/B000000000/ref=sr_1_3?crid=ABC&keywords=x&qid=1&sr=8-3&tag=aff-20&th=1&psc=1&pd_rd_r=zz',
|
|
),
|
|
'https://www.amazon.com/dp/B000000000?keywords=x&th=1&psc=1',
|
|
);
|
|
});
|
|
|
|
it('never rewrites matrix.to permalinks or non-http schemes', () => {
|
|
const permalink = 'https://matrix.to/#/!room:example.org/$event?via=example.org&utm_source=x';
|
|
assert.equal(stripTrackingParams(permalink), permalink);
|
|
assert.equal(
|
|
stripTrackingParams('mxc://example.org/abc?utm_source=x'),
|
|
'mxc://example.org/abc?utm_source=x',
|
|
);
|
|
assert.equal(stripTrackingParams('mailto:a@b.c?utm_source=x'), 'mailto:a@b.c?utm_source=x');
|
|
});
|
|
|
|
it('returns unparseable input unchanged', () => {
|
|
assert.equal(stripTrackingParams('https://'), 'https://');
|
|
assert.equal(stripTrackingParams('not a url'), 'not a url');
|
|
});
|
|
|
|
it('is idempotent', () => {
|
|
const once = stripTrackingParams('https://x.com/user/status/1?s=20&t=abc');
|
|
assert.equal(once, 'https://x.com/user/status/1');
|
|
assert.equal(stripTrackingParams(once), once);
|
|
});
|
|
});
|
|
|
|
describe('stripTrackingParamsInText', () => {
|
|
it('cleans every URL in a block of text and keeps trailing punctuation', () => {
|
|
const text =
|
|
'see https://a.example/p?utm_source=x. and (https://b.example/?id=1&fbclid=2) plus https://c.example/?keep=1';
|
|
assert.equal(
|
|
stripTrackingParamsInText(text),
|
|
'see https://a.example/p. and (https://b.example/?id=1) plus https://c.example/?keep=1',
|
|
);
|
|
});
|
|
|
|
it('returns the identical string when no URL changed', () => {
|
|
const text = 'nothing https://c.example/?keep=1 here';
|
|
assert.equal(stripTrackingParamsInText(text), text);
|
|
});
|
|
});
|
|
|
|
describe('stripTrackingParamsInHtml', () => {
|
|
it('unescapes & for parsing and re-escapes in the output', () => {
|
|
const html =
|
|
'<a href="https://a.example/p?id=1&utm_source=x&page=2">https://a.example/p?id=1&utm_source=x&page=2</a>';
|
|
assert.equal(
|
|
stripTrackingParamsInHtml(html),
|
|
'<a href="https://a.example/p?id=1&page=2">https://a.example/p?id=1&page=2</a>',
|
|
);
|
|
});
|
|
|
|
it('leaves markup untouched when nothing is stripped', () => {
|
|
const html = '<p>hi <a href="https://a.example/?x=1">link</a></p>';
|
|
assert.equal(stripTrackingParamsInHtml(html), html);
|
|
});
|
|
});
|
|
|
|
it('[#280] Reddit keeps context= (it shows the parent comments) but drops share_id', () => {
|
|
assert.equal(
|
|
stripTrackingParams('https://www.reddit.com/r/x/comments/abc/def/xyz/?context=3&share_id=1'),
|
|
'https://www.reddit.com/r/x/comments/abc/def/xyz/?context=3',
|
|
);
|
|
});
|