import { describe, expect, test } from 'bun:test'; import { checkUrlTargeting, testRegex } from './url-match'; describe('testRegex', () => { test('returns true for matching regex', () => { expect(testRegex('hello', 'hello world')).toBe(true); expect(testRegex('^https://', 'https://example.com')).toBe(true); expect(testRegex('/products/\\d+', '/products/123')).toBe(true); }); test('returns false for non-matching regex', () => { expect(testRegex('^https://', 'http://example.com')).toBe(false); expect(testRegex('/products/\\d+$', '/products/abc')).toBe(false); }); test('returns false for invalid regex', () => { expect(testRegex('[invalid', 'test')).toBe(false); expect(testRegex('(unclosed', 'test')).toBe(false); }); }); describe('checkUrlTargeting', () => { describe('empty targeting', () => { test('returns true for empty targeting array', () => { expect(checkUrlTargeting([], 'https://example.com')).toBe(true); }); }); describe('equals condition', () => { test('matches exact URL', () => { const targeting = [{ url: 'https://example.com/page', condition: 'equals' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true); }); test('does not match different URL', () => { const targeting = [{ url: 'https://example.com/page', condition: 'equals' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/other')).toBe(false); }); test('ignores trailing slashes', () => { const targeting = [{ url: 'https://example.com/page/', condition: 'equals' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true); }); }); describe('not equals condition', () => { test('matches when URL is different', () => { const targeting = [{ url: 'https://example.com/page', condition: 'not equals' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/other')).toBe(true); }); test('does not match when URL is same', () => { const targeting = [{ url: 'https://example.com/page', condition: 'not equals' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false); }); }); describe('contains condition', () => { test('matches when URL contains substring', () => { const targeting = [{ url: 'example', condition: 'contains' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true); }); test('matches partial path', () => { const targeting = [{ url: '/products/', condition: 'contains' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/products/123')).toBe(true); }); test('does not match when substring not present', () => { const targeting = [{ url: 'foobar', condition: 'contains' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false); }); }); describe('does not contain condition', () => { test('matches when URL does not contain substring', () => { const targeting = [{ url: 'admin', condition: 'does not contain' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true); }); test('does not match when URL contains substring', () => { const targeting = [{ url: 'example', condition: 'does not contain' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false); }); }); describe('starts with condition', () => { test('matches URL starting with prefix', () => { const targeting = [{ url: 'https://example.com', condition: 'starts with' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(true); }); test('does not match URL with different start', () => { const targeting = [{ url: 'https://other.com', condition: 'starts with' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false); }); }); describe('ends with condition', () => { test('matches URL ending with suffix', () => { const targeting = [{ url: '/checkout', condition: 'ends with' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/checkout')).toBe(true); }); test('does not match URL with different ending', () => { const targeting = [{ url: '/checkout', condition: 'ends with' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/cart')).toBe(false); }); }); describe('matches regex condition', () => { test('matches valid regex pattern', () => { const targeting = [{ url: '/products/\\d+', condition: 'matches regex' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/products/123')).toBe(true); }); test('does not match non-matching pattern', () => { const targeting = [{ url: '/products/\\d+$', condition: 'matches regex' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/products/abc')).toBe(false); }); test('handles invalid regex gracefully', () => { const targeting = [{ url: '[invalid', condition: 'matches regex' as const }]; expect(checkUrlTargeting(targeting, 'https://example.com/page')).toBe(false); }); }); describe('multiple targeting rules', () => { test('returns true if any rule matches (OR logic)', () => { const targeting = [ { url: '/admin', condition: 'contains' as const }, { url: '/dashboard', condition: 'contains' as const }, ]; expect(checkUrlTargeting(targeting, 'https://example.com/dashboard')).toBe(true); }); test('returns false if no rules match', () => { const targeting = [ { url: '/admin', condition: 'contains' as const }, { url: '/dashboard', condition: 'contains' as const }, ]; expect(checkUrlTargeting(targeting, 'https://example.com/home')).toBe(false); }); test('first matching rule short-circuits', () => { const targeting = [ { url: 'example', condition: 'contains' as const }, { url: '[invalid', condition: 'matches regex' as const }, // invalid, but won't be checked ]; expect(checkUrlTargeting(targeting, 'https://example.com')).toBe(true); }); }); });