项目文件夹

文件
2026-07-13 12:34:04 +08:00

262 行
9.5 KiB
JavaScript

'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
// Mock globals needed at module load time
globalThis.TabHarborI18n = {};
// Prevent top-level DOM code from throwing
globalThis.document = {
addEventListener: () => {},
createElement: () => ({ style: {} }),
getElementById: () => null,
};
globalThis.window = globalThis;
require('./ui-helpers.js');
const {
friendlyDomain,
stripTitleNoise,
cleanTitle,
smartTitle,
capitalize,
} = globalThis;
// ---- capitalize ----
test('capitalize uppercases first letter', () => {
assert.equal(capitalize('github'), 'Github');
assert.equal(capitalize('hello world'), 'Hello world');
});
test('capitalize handles empty string', () => {
assert.equal(capitalize(''), '');
});
test('capitalize handles null/undefined', () => {
assert.equal(capitalize(null), '');
assert.equal(capitalize(undefined), '');
});
// ---- friendlyDomain ----
test('friendlyDomain returns friendly name for known domains', () => {
assert.equal(friendlyDomain('github.com'), 'GitHub');
assert.equal(friendlyDomain('www.github.com'), 'GitHub');
assert.equal(friendlyDomain('youtube.com'), 'YouTube');
assert.equal(friendlyDomain('mail.google.com'), 'Gmail');
assert.equal(friendlyDomain('developer.mozilla.org'), 'MDN');
assert.equal(friendlyDomain('chatgpt.com'), 'ChatGPT');
assert.equal(friendlyDomain('claude.ai'), 'Claude');
assert.equal(friendlyDomain('news.ycombinator.com'), 'Hacker News');
});
test('friendlyDomain handles substack subdomains', () => {
assert.equal(friendlyDomain('example.substack.com'), "Example's Substack");
});
test('friendlyDomain handles github.io pages', () => {
assert.equal(friendlyDomain('myproject.github.io'), 'Myproject (GitHub Pages)');
});
test('friendlyDomain strips www and TLD then capitalizes unknown domains', () => {
assert.equal(friendlyDomain('www.example.org'), 'Example');
assert.equal(friendlyDomain('mail.somecompany.co.uk'), 'Mail Somecompany');
});
test('friendlyDomain capitalizes multi-part unknown domains', () => {
assert.equal(friendlyDomain('api.internal.example.com'), 'Api Internal Example');
});
test('friendlyDomain handles empty/null input', () => {
assert.equal(friendlyDomain(''), '');
assert.equal(friendlyDomain(null), '');
assert.equal(friendlyDomain(undefined), '');
});
test('friendlyDomain handles local-files special domain', () => {
assert.equal(friendlyDomain('local-files'), 'Local Files');
});
// ---- stripTitleNoise ----
test('stripTitleNoise removes notification count prefix', () => {
assert.equal(stripTitleNoise('(3) GitHub'), 'GitHub');
assert.equal(stripTitleNoise('(99+) Messages'), 'Messages');
});
test('stripTitleNoise removes inline notification counts', () => {
assert.equal(stripTitleNoise('Inbox (5+) new'), 'Inbox new');
assert.equal(stripTitleNoise('Title (1,234)'), 'Title');
});
test('stripTitleNoise removes email noise after dash separators', () => {
assert.equal(stripTitleNoise('Check - user@example.com'), 'Check');
assert.equal(stripTitleNoise('Inbox – admin@site.org mail'), 'Inbox mail');
});
test('stripTitleNoise removes bare email addresses', () => {
assert.equal(stripTitleNoise('Contact user@example.com here'), 'Contact here');
});
test('stripTitleNoise handles on X: replacement', () => {
assert.equal(stripTitleNoise('Post on X: hello world'), 'Post: hello world');
});
test('stripTitleNoise strips trailing / X', () => {
assert.equal(stripTitleNoise('Share / X'), 'Share');
assert.equal(stripTitleNoise('Article / X'), 'Article');
});
test('stripTitleNoise returns clean title unchanged', () => {
assert.equal(stripTitleNoise('Clean Title'), 'Clean Title');
assert.equal(stripTitleNoise('No noise here'), 'No noise here');
});
test('stripTitleNoise trims whitespace', () => {
assert.equal(stripTitleNoise(' Title '), 'Title');
});
test('stripTitleNoise handles empty string', () => {
assert.equal(stripTitleNoise(''), '');
});
// ---- cleanTitle ----
test('cleanTitle strips suffix when it matches exact domain', () => {
assert.equal(cleanTitle('My Page - example.com', 'example.com'), 'My Page');
assert.equal(cleanTitle('Dashboard | example.com', 'www.example.com'), 'Dashboard');
});
test('cleanTitle strips suffix when it matches friendly domain (capitalized)', () => {
// friendlyDomain('example.com') → 'Example'. suffix 'Example' matches.
assert.equal(cleanTitle('Dashboard | Example', 'example.com'), 'Dashboard');
});
test('cleanTitle strips suffix when it matches domain without TLD', () => {
// friendlyDomain('example.com') → 'Example'. suffix 'example' matches domain without .com
// Title must be >= 5 chars after stripping
assert.equal(cleanTitle('Welcome Page — example', 'example.com'), 'Welcome Page');
});
test('cleanTitle strips suffix when domain includes suffix', () => {
assert.equal(cleanTitle('API Reference - api', 'api.example.com'), 'API Reference');
});
test('cleanTitle keeps title when suffix does not match domain', () => {
assert.equal(cleanTitle('GitHub - awesome-org', 'github.com'), 'GitHub - awesome-org');
assert.equal(cleanTitle('Random Text | unrelated site', 'example.com'), 'Random Text | unrelated site');
});
test('cleanTitle keeps short cleaned titles (under 5 chars)', () => {
assert.equal(cleanTitle('AB - example.com', 'example.com'), 'AB - example.com');
});
test('cleanTitle handles all separator types', () => {
assert.equal(cleanTitle('Title · example.com', 'example.com'), 'Title');
assert.equal(cleanTitle('Title – example.com', 'example.com'), 'Title');
assert.equal(cleanTitle('Title — example.com', 'example.com'), 'Title');
});
test('cleanTitle strips www from domain before matching', () => {
assert.equal(cleanTitle('Page - www.example.com', 'www.example.com'), 'Page - www.example.com');
});
test('cleanTitle handles empty title or hostname', () => {
assert.equal(cleanTitle('', 'example.com'), '');
assert.equal(cleanTitle('Title', ''), 'Title');
});
test('cleanTitle handles separator with domain-friendly-includes match', () => {
// friendlyDomain('example.com') returns 'Example' (stripped TLD + capitalized)
// 'example.com'.toLowerCase().includes('example') → true ✓
assert.equal(cleanTitle('Site Name - example', 'example.com'), 'Site Name');
});
test('cleanTitle handles known domain friendly names in suffix matching', () => {
// friendlyDomain('github.com') returns 'GitHub'
assert.equal(cleanTitle('My Repos - GitHub', 'github.com'), 'My Repos');
assert.equal(cleanTitle('Dashboard | GitHub', 'github.com'), 'Dashboard');
});
// ---- smartTitle ----
test('smartTitle returns YouTube Video for youtube watch pages with URL-like title', () => {
assert.equal(smartTitle('https://www.youtube.com/watch?v=abc', 'https://www.youtube.com/watch?v=abc'), 'YouTube Video');
assert.equal(smartTitle('', 'https://www.youtube.com/watch?v=abc'), 'YouTube Video');
});
test('smartTitle returns original title for youtube watch with meaningful title', () => {
assert.equal(smartTitle('Cool Video', 'https://www.youtube.com/watch?v=abc'), 'Cool Video');
});
test('smartTitle returns Post by @username for x.com status URLs with URL-like title', () => {
assert.equal(smartTitle('https://x.com/jack/status/123', 'https://x.com/jack/status/123'), 'Post by @jack');
assert.equal(smartTitle('', 'https://twitter.com/elonmusk/status/456'), 'Post by @elonmusk');
});
test('smartTitle returns original title for x.com status with meaningful title', () => {
assert.equal(smartTitle('Interesting take', 'https://x.com/user/status/789'), 'Interesting take');
});
test('smartTitle returns GitHub issue title for issue URLs with URL-like title', () => {
assert.equal(
smartTitle('https://github.com/owner/repo/issues/42', 'https://github.com/owner/repo/issues/42'),
'owner/repo Issue #42'
);
});
test('smartTitle returns GitHub PR title for PR URLs with URL-like title', () => {
assert.equal(
smartTitle('', 'https://github.com/owner/repo/pull/100'),
'owner/repo PR #100'
);
});
test('smartTitle returns URL as title when original title is empty', () => {
assert.equal(smartTitle('', 'https://www.example.com/path'), 'https://www.example.com/path');
});
test('smartTitle returns title when it is not URL-like', () => {
assert.equal(smartTitle('My Page Title', 'https://www.example.com'), 'My Page Title');
});
test('smartTitle handles empty URL', () => {
assert.equal(smartTitle('Title', ''), 'Title');
assert.equal(smartTitle('', ''), '');
});
test('smartTitle handles invalid URL gracefully', () => {
assert.equal(smartTitle('', 'not-a-url'), '');
});
test('smartTitle does not treat youtube non-watch pages as video', () => {
assert.equal(
smartTitle('', 'https://www.youtube.com/results?search_query=foo'),
'https://www.youtube.com/results?search_query=foo'
);
});
test('smartTitle does not mangle title that starts with hostname but is actual text', () => {
// titleIsUrl checks title.startsWith(hostname) — but the real title is text
// e.g. "github.com is great" with url "https://github.com"
const label = smartTitle('github.com is great', 'https://github.com');
assert.equal(label, 'github.com is great');
});
test('smartTitle handles Reddit post URLs', () => {
assert.equal(
smartTitle('https://www.reddit.com/r/programming/comments/abc/title', 'https://www.reddit.com/r/programming/comments/abc/title'),
'r/programming post'
);
});
test('capitalize handles empty string', () => {
assert.equal(capitalize(''), '');
});
test('capitalize handles single character', () => {
assert.equal(capitalize('a'), 'A');
});