Files
AeroFetch/test/clipboardLink.test.ts
T
debont80 8ab85da67e Fix H5/H6/M21/L37-40/L47/L55/L68/L72/L76/L91/L98/L108/L165/L166 audit items
H5: HistoryEntry now stores formatId+formatHasAudio; redownload passes them
    back to addFromUrl so the original yt-dlp format is reused, not guessed.
    Compound quality labels stripped to the preset prefix for old history.
L72: thumbnail now passed in redownload so re-queued rows keep their art.
H6: TerminalView log capped at MAX_LOG_LINES=2000 to prevent unbounded growth.
M21: --audio-quality omitted for lossless audioFormats (flac/wav).
L166: fmtEta hour rollover fixed in all 3 locations -- 2h00:00 not 120:00.
L165: queueStats formatSpeed precision aligned with fmtBytes.
L55: QueueItem suppresses sizeLabel when already in probed-format quality label.
L47: probeMeta null sends empty meta event so Resolving clears via SR6.
L68: notifiedBackground resets on window show for subsequent close-while-downloading.
L76: dup warning falls back to URL when title is still a placeholder.
L91: SettingsView onFormatSelect uses indexOf instead of unsafe tuple cast.
L98: Embed chapters field gets a hint text.
L108: BrowserWindow created with explicit title AeroFetch.
L37: pure formatters extracted to src/main/lib/formatters.ts and unit-tested.
L38: buildArgs test covers webm thumbnail suppression.
L39: CROP_SQUARE_PPA test is structural not exact-string.
L40: looksLikeUrl/looksLikeSingleVideo extracted to src/renderer/src/lib/urlHelpers.ts.

typecheck + 242 tests + eslint + prettier green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 13:29:35 -04:00

77 lines
3.4 KiB
TypeScript

import { describe, it, expect } from 'vitest'
// Import from the pure utility module directly — no Zustand store init needed (L40).
import { looksLikeUrl, looksLikeSingleVideo } from '../src/renderer/src/lib/urlHelpers'
describe('looksLikeUrl', () => {
it('accepts http(s) URLs', () => {
expect(looksLikeUrl('https://youtube.com/watch?v=abc')).toBe(true)
expect(looksLikeUrl('http://example.com')).toBe(true)
expect(looksLikeUrl('https://example.com/a/b?c=d#frag')).toBe(true)
})
it('is scheme-case-insensitive', () => {
expect(looksLikeUrl('HTTPS://example.com')).toBe(true)
expect(looksLikeUrl('HtTp://example.com')).toBe(true)
})
it('trims surrounding whitespace', () => {
expect(looksLikeUrl(' https://example.com\n')).toBe(true)
expect(looksLikeUrl('\t http://example.com \t')).toBe(true)
})
it('rejects non-http(s) schemes', () => {
expect(looksLikeUrl('ftp://example.com')).toBe(false)
expect(looksLikeUrl('file:///c:/x')).toBe(false)
expect(looksLikeUrl('magnet:?xt=urn:btih:abc')).toBe(false)
expect(looksLikeUrl('javascript:alert(1)')).toBe(false)
expect(looksLikeUrl('mailto:a@b.com')).toBe(false)
})
it('rejects bare domains and scheme-less text', () => {
expect(looksLikeUrl('www.example.com')).toBe(false)
expect(looksLikeUrl('example.com/watch')).toBe(false)
expect(looksLikeUrl('see http://example.com')).toBe(false) // must start with the scheme
})
it('rejects empty, whitespace, and malformed input', () => {
expect(looksLikeUrl('')).toBe(false)
expect(looksLikeUrl(' ')).toBe(false)
expect(looksLikeUrl('not a link')).toBe(false)
expect(looksLikeUrl('http://')).toBe(false) // passes the prefix test but is not a valid URL
})
})
describe('looksLikeSingleVideo', () => {
it('flags YouTube single-video URLs', () => {
expect(looksLikeSingleVideo('https://www.youtube.com/watch?v=dQw4w9WgXcQ')).toBe(true)
expect(looksLikeSingleVideo('https://youtube.com/watch?v=abc123')).toBe(true)
expect(looksLikeSingleVideo('https://m.youtube.com/watch?v=abc123')).toBe(true)
expect(looksLikeSingleVideo('https://music.youtube.com/watch?v=abc123')).toBe(true)
expect(looksLikeSingleVideo('https://youtu.be/dQw4w9WgXcQ')).toBe(true)
})
it('keeps anything with a playlist context (?list=)', () => {
// A video opened in a playlist → the user likely wants the whole playlist.
expect(looksLikeSingleVideo('https://www.youtube.com/watch?v=abc&list=PL123')).toBe(false)
expect(looksLikeSingleVideo('https://youtu.be/abc?list=PL123')).toBe(false)
})
it('keeps channels and playlists', () => {
expect(looksLikeSingleVideo('https://www.youtube.com/@SomeChannel')).toBe(false)
expect(looksLikeSingleVideo('https://www.youtube.com/channel/UC123')).toBe(false)
expect(looksLikeSingleVideo('https://www.youtube.com/c/SomeChannel')).toBe(false)
expect(looksLikeSingleVideo('https://www.youtube.com/playlist?list=PL123')).toBe(false)
})
it('does not flag single videos on other sites (conservative)', () => {
// We can't reliably classify arbitrary hosts, so never reject them.
expect(looksLikeSingleVideo('https://vimeo.com/123456789')).toBe(false)
expect(looksLikeSingleVideo('https://example.com/watch?v=abc')).toBe(false)
})
it('returns false for non-URLs', () => {
expect(looksLikeSingleVideo('not a url')).toBe(false)
expect(looksLikeSingleVideo('')).toBe(false)
})
})