getValue())->toBe('+49 123 456789'); }); it('creates phone number with parse method', function () { $phone = PhoneNumber::parse('+49-123-456-789'); expect($phone->getValue())->toBe('+49 123 456 789'); }); it('throws exception for empty phone number', function () { expect(fn () => PhoneNumber::from('')) ->toThrow(InvalidArgumentException::class, 'Phone number cannot be empty.'); }); it('throws exception for phone number without digits', function () { expect(fn () => PhoneNumber::from('abc')) ->toThrow(InvalidArgumentException::class, 'Phone number must contain digits: abc'); }); it('throws exception for too short phone number', function () { expect(fn () => PhoneNumber::from('123')) ->toThrow(InvalidArgumentException::class, 'Phone number too short: 123'); }); it('throws exception for too long phone number', function () { expect(fn () => PhoneNumber::from('123456789012345678901')) ->toThrow(InvalidArgumentException::class, 'Phone number too long: 123456789012345678901'); }); it('throws exception for invalid format', function () { expect(fn () => PhoneNumber::from('+49#123#456')) ->toThrow(InvalidArgumentException::class, 'Invalid phone number format: +49#123#456'); }); it('validates phone numbers correctly', function () { expect(PhoneNumber::isValid('+49 123 456789'))->toBeTrue(); expect(PhoneNumber::isValid('0123 456789'))->toBeTrue(); expect(PhoneNumber::isValid('+1 (555) 123-4567'))->toBeTrue(); expect(PhoneNumber::isValid(''))->toBeFalse(); expect(PhoneNumber::isValid('abc'))->toBeFalse(); expect(PhoneNumber::isValid('123'))->toBeFalse(); }); it('extracts country code correctly', function () { $phone1 = PhoneNumber::from('+49 123 456789'); expect($phone1->getCountryCode())->toBe('49'); $phone2 = PhoneNumber::from('+1 555 123 4567'); expect($phone2->getCountryCode())->toBe('1'); $phone3 = PhoneNumber::from('0123 456789'); expect($phone3->getCountryCode())->toBeNull(); }); it('extracts national number correctly', function () { $phone1 = PhoneNumber::from('+49 123 456789'); expect($phone1->getNationalNumber())->toBe(' 123 456789'); $phone2 = PhoneNumber::from('0123 456789'); expect($phone2->getNationalNumber())->toBe('0123 456789'); }); it('detects mobile numbers correctly', function () { // German mobile numbers $mobile1 = PhoneNumber::from('+49 15 12345678'); expect($mobile1->isMobile())->toBeTrue(); $mobile2 = PhoneNumber::from('+49 16 12345678'); expect($mobile2->isMobile())->toBeTrue(); $mobile3 = PhoneNumber::from('+49 17 12345678'); expect($mobile3->isMobile())->toBeTrue(); // German landline $landline = PhoneNumber::from('+49 30 12345678'); expect($landline->isMobile())->toBeFalse(); // US numbers (10 digits are considered mobile for demo) $usMobile = PhoneNumber::from('+1 555 123 4567'); expect($usMobile->isMobile())->toBeTrue(); // General heuristic: 10+ digits $longNumber = PhoneNumber::from('+999 1234567890'); expect($longNumber->isMobile())->toBeTrue(); }); it('formats to E164 correctly', function () { $phone1 = PhoneNumber::from('+49 123 456 789'); expect($phone1->toE164())->toBe('+49123456789'); $phone2 = PhoneNumber::from('0123 456789'); expect($phone2->toE164())->toBe('+49123456789'); // Assumes German for demo $phone3 = PhoneNumber::from('+1 (555) 123-4567'); expect($phone3->toE164())->toBe('+15551234567'); }); it('formats to international display format', function () { $phone1 = PhoneNumber::from('+49 123456789'); $international = $phone1->toInternational(); expect($international)->toContain('+49'); expect($international)->toContain('123'); $phone2 = PhoneNumber::from('+1 5551234567'); $international2 = $phone2->toInternational(); expect($international2)->toContain('+1'); expect($international2)->toContain('555'); }); it('formats to national display format', function () { $phone1 = PhoneNumber::from('+49 123456789'); $national = $phone1->toNational(); expect($national)->toContain('0'); // German national format starts with 0 expect($national)->toContain('123'); $phone2 = PhoneNumber::from('+1 5551234567'); $national2 = $phone2->toNational(); expect($national2)->toContain('(555)'); // US format with parentheses }); it('compares phone numbers correctly', function () { $phone1 = PhoneNumber::from('+49 123 456789'); $phone2 = PhoneNumber::from('+49-123-456-789'); $phone3 = PhoneNumber::from('+1 555 123 4567'); expect($phone1->equals($phone2))->toBeTrue(); // Same number, different formatting expect($phone1->equals($phone3))->toBeFalse(); // Different numbers }); it('checks same country correctly', function () { $phone1 = PhoneNumber::from('+49 123 456789'); $phone2 = PhoneNumber::from('+49 987 654321'); $phone3 = PhoneNumber::from('+1 555 123 4567'); expect($phone1->isSameCountry($phone2))->toBeTrue(); expect($phone1->isSameCountry($phone3))->toBeFalse(); }); it('converts to string correctly', function () { $phone = PhoneNumber::from('+49 123 456789'); expect((string)$phone)->toBe('+49 123 456789'); expect($phone->__toString())->toBe('+49 123 456789'); }); it('handles various input formats', function () { $formats = [ '+49 123 456789', '+49-123-456-789', '+49.123.456.789', '+49 (123) 456-789', '0049 123 456789', '0123 456789', '123456789', ]; foreach ($formats as $format) { $phone = PhoneNumber::parse($format); expect($phone)->toBeInstanceOf(PhoneNumber::class); expect(strlen($phone->getValue()))->toBeGreaterThan(8); } }); it('normalizes input correctly', function () { $phone1 = PhoneNumber::parse('+49--123..456((789))'); expect($phone1->getValue())->toBe('+49 123 456 789'); $phone2 = PhoneNumber::parse(' +49 123 456 789 '); expect($phone2->getValue())->toBe('+49 123 456 789'); }); });