import { describe, it, expect } from 'bun:test';
import {
isValidUrl,
normalizeUrl,
getBaseDomain,
isSameDomain,
matchesPattern,
resolveUrl,
} from '@/utils/url.js';
describe('url utilities', () => {
describe('isValidUrl', () => {
it('should return true for valid urls', () => {
expect(isValidUrl('https://example.com')).toBe(true);
expect(isValidUrl('http://example.com/path')).toBe(true);
expect(isValidUrl('https://docs.example.com/api/v1')).toBe(true);
});
it('should return false for invalid urls', () => {
expect(isValidUrl('not-a-url')).toBe(false);
expect(isValidUrl('ftp://example.com')).toBe(true); // ftp is valid
expect(isValidUrl('')).toBe(false);
expect(isValidUrl('example.com')).toBe(false);
});
});
describe('normalizeUrl', () => {
it('should remove hash fragments', () => {
expect(normalizeUrl('https://example.com/page#section')).toBe('https://example.com/page');
});
it('should remove trailing slash from paths', () => {
expect(normalizeUrl('https://example.com/path/')).toBe('https://example.com/path');
expect(normalizeUrl('https://example.com/')).toBe('https://example.com/');
});
it('should preserve query parameters', () => {
expect(normalizeUrl('https://example.com/search?q=test')).toBe('https://example.com/search?q=test');
});
});
describe('getBaseDomain', () => {
it('should extract base domain', () => {
expect(getBaseDomain('https://docs.example.com/path')).toBe('https://docs.example.com');
expect(getBaseDomain('http://example.com:8080/api')).toBe('http://example.com:8080');
});
});
describe('isSameDomain', () => {
it('should return true for same domains', () => {
expect(isSameDomain('https://example.com/page1', 'https://example.com/page2')).toBe(true);
expect(isSameDomain('http://docs.example.com/a', 'http://docs.example.com/b')).toBe(true);
});
it('should return false for different domains', () => {
expect(isSameDomain('https://example.com/page', 'https://other.com/page')).toBe(false);
expect(isSameDomain('http://example.com/page', 'https://example.com/page')).toBe(false);
});
});
describe('matchesPattern', () => {
it('should match wildcard patterns', () => {
expect(matchesPattern('https://example.com/docs/api', ['/docs/*'])).toBe(true);
expect(matchesPattern('https://example.com/file.pdf', ['*.pdf'])).toBe(true);
});
it('should not match non-matching patterns', () => {
expect(matchesPattern('https://example.com/blog/post', ['/docs/*'])).toBe(false);
expect(matchesPattern('https://example.com/file.html', ['*.pdf'])).toBe(false);
});
it('should return false for empty patterns', () => {
expect(matchesPattern('https://example.com/anything', [])).toBe(false);
});
});
describe('resolveUrl', () => {
it('should resolve relative urls', () => {
expect(resolveUrl('https://example.com/docs/', 'api.html')).toBe('https://example.com/docs/api.html');
expect(resolveUrl('https://example.com/docs/', '../other.html')).toBe('https://example.com/other.html');
});
it('should handle absolute urls', () => {
expect(resolveUrl('https://example.com/', 'https://other.com/page')).toBe('https://other.com/page');
});
it('should return original on invalid input', () => {
expect(resolveUrl('invalid-base', 'relative')).toBe('relative');
});
});
});