waybetter-for-x/apps/desktop/tests/addressModel.test.ts
2026-10-01 06:01:13 +07:00

132 lines
5 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { parseAddress } from '../src/shell/addressModel.ts';
function labels(url: string, wording: 'twitter' | 'x' = 'x') {
const model = parseAddress(url, wording);
return model ? model.segments.map((s) => s.label) : null;
}
test('home', () => {
assert.deepEqual(labels('https://x.com/home'), ['Home']);
assert.deepEqual(labels('https://x.com/'), ['Home']);
});
test('search with quoted truncated query', () => {
const long = 'a'.repeat(60);
const model = parseAddress(`https://x.com/search?q=${long}`, 'x');
assert.ok(model);
assert.equal(model!.segments[0].label, 'Search');
const quoted = model!.segments[1];
assert.ok(quoted.quoted);
assert.ok(quoted.label.length <= 42);
assert.ok(quoted.label.endsWith('…"'));
});
test('notifications and mentions', () => {
assert.deepEqual(labels('https://x.com/notifications'), ['Notifications']);
assert.deepEqual(labels('https://x.com/notifications/mentions'), ['Notifications', 'Mentions']);
});
test('messages with mono last6 id', () => {
const model = parseAddress('https://x.com/messages/1234567890', 'x');
assert.ok(model);
assert.equal(model!.segments[0].label, 'Messages');
assert.equal(model!.segments[1].label, '…567890');
assert.ok(model!.segments[1].mono);
});
test('bookmarks, lists and communities', () => {
assert.deepEqual(labels('https://x.com/i/bookmarks'), ['Bookmarks']);
assert.deepEqual(labels('https://x.com/i/lists/9876543210'), ['Lists', '…543210']);
assert.deepEqual(labels('https://x.com/i/communities/1112223334'), ['Communities', '…223334']);
});
test('explore with capitalised tab', () => {
assert.deepEqual(labels('https://x.com/explore'), ['Explore']);
assert.deepEqual(labels('https://x.com/explore/tabs/trending'), ['Explore', 'Trending']);
});
test('settings parts are title-cased', () => {
assert.deepEqual(labels('https://x.com/settings/account/username'), ['Settings', 'Account', 'Username']);
});
test('user profile chip', () => {
assert.deepEqual(labels('https://x.com/jack'), ['@jack']);
});
test('reserved paths are not treated as usernames', () => {
assert.deepEqual(labels('https://x.com/home'), ['Home']);
assert.deepEqual(labels('https://x.com/explore'), ['Explore']);
assert.deepEqual(labels('https://x.com/settings'), ['Settings']);
assert.deepEqual(labels('https://x.com/i/bookmarks'), ['Bookmarks']);
});
test('status url with mono last6 id', () => {
const model = parseAddress('https://x.com/jack/status/1234567890123', 'x');
assert.ok(model);
assert.deepEqual(
model!.segments.map((s) => s.label),
['@jack', 'Post', '…890123'],
);
assert.ok(model!.segments[2].mono);
});
test('status photo suffix', () => {
assert.deepEqual(
labels('https://x.com/jack/status/1234567890123/photo/2'),
['@jack', 'Post', '…890123', 'Photo 2'],
);
});
test('status analytics suffix', () => {
assert.deepEqual(
labels('https://x.com/jack/status/1234567890123/analytics'),
['@jack', 'Post', '…890123', 'Analytics'],
);
});
test('user subpages', () => {
assert.deepEqual(labels('https://x.com/jack/with_replies'), ['@jack', 'Replies']);
assert.deepEqual(labels('https://x.com/jack/media'), ['@jack', 'Media']);
assert.deepEqual(labels('https://x.com/jack/likes'), ['@jack', 'Likes']);
assert.deepEqual(labels('https://x.com/jack/followers'), ['@jack', 'Followers']);
assert.deepEqual(labels('https://x.com/jack/following'), ['@jack', 'Following']);
});
test('twitter.com behaves the same as x.com', () => {
assert.deepEqual(labels('https://twitter.com/home'), labels('https://x.com/home'));
assert.deepEqual(labels('https://twitter.com/jack/status/42'), labels('https://x.com/jack/status/42'));
});
test('site chip label follows wording setting', () => {
assert.equal(parseAddress('https://x.com/home', 'x')!.site.label, 'X');
assert.equal(parseAddress('https://x.com/home', 'twitter')!.site.label, 'Twitter');
});
test('http url is flagged insecure', () => {
const model = parseAddress('http://x.com/home', 'x');
assert.ok(model);
assert.equal(model!.insecure, true);
assert.equal(parseAddress('https://x.com/home', 'x')!.insecure, false);
});
test('other hosts show hostname without www and truncated path parts', () => {
const model = parseAddress('https://www.example.com/some/very/long/path/segment/name/that/is/too/long', 'x');
assert.ok(model);
assert.equal(model!.site.kind, 'host');
assert.equal(model!.site.label, 'example.com');
assert.ok(model!.segments[0].label.length <= 24);
});
test('non-empty query on other hosts shows a trailing chip', () => {
const model = parseAddress('https://example.com/path?x=1', 'x');
assert.ok(model);
assert.equal(model!.segments[model!.segments.length - 1].label, '?…');
});
test('about and file schemes and invalid urls are unparsable', () => {
assert.equal(parseAddress('about:blank', 'x'), null);
assert.equal(parseAddress('file:///etc/passwd', 'x'), null);
assert.equal(parseAddress('not a url', 'x'), null);
});