154 lines
6.2 KiB
TypeScript
154 lines
6.2 KiB
TypeScript
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);
|
|
});
|
|
});
|
|
});
|