parse($ua); expect($parsed)->toBeInstanceOf(ParsedUserAgent::class); expect($parsed->browser)->toBe(BrowserType::CHROME); expect($parsed->browserVersion)->toBeInstanceOf(Version::class); expect($parsed->browserVersion->getMajor())->toBe(120); expect($parsed->platform)->toBe(PlatformType::WINDOWS); expect($parsed->engine)->toBe(EngineType::BLINK); expect($parsed->isModern)->toBeTrue(); expect($parsed->isMobile)->toBeFalse(); expect($parsed->isBot)->toBeFalse(); }); it('parses Firefox User-Agent with Version value objects', function () { $parser = new UserAgentParser(); $ua = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0'; $parsed = $parser->parse($ua); expect($parsed->browser)->toBe(BrowserType::FIREFOX); expect($parsed->browserVersion)->toBeInstanceOf(Version::class); expect($parsed->browserVersion->getMajor())->toBe(115); expect($parsed->platform)->toBe(PlatformType::LINUX); expect($parsed->engine)->toBe(EngineType::GECKO); expect($parsed->isModern)->toBeTrue(); }); it('parses Safari User-Agent with Version value objects', function () { $parser = new UserAgentParser(); $ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15'; $parsed = $parser->parse($ua); expect($parsed->browser)->toBe(BrowserType::SAFARI); expect($parsed->browserVersion)->toBeInstanceOf(Version::class); expect($parsed->browserVersion->getMajor())->toBe(16); expect($parsed->platform)->toBe(PlatformType::MACOS); expect($parsed->engine)->toBe(EngineType::WEBKIT); }); it('parses mobile Chrome User-Agent', function () { $parser = new UserAgentParser(); $ua = 'Mozilla/5.0 (Linux; Android 13; SM-S918B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36'; $parsed = $parser->parse($ua); expect($parsed->browser)->toBe(BrowserType::CHROME); expect($parsed->platform)->toBe(PlatformType::ANDROID); expect($parsed->isMobile)->toBeTrue(); expect($parsed->isBot)->toBeFalse(); }); it('detects bot User-Agent', function () { $parser = new UserAgentParser(); $ua = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'; $parsed = $parser->parse($ua); expect($parsed->isBot)->toBeTrue(); expect($parsed->isModern)->toBeFalse(); }); it('handles empty User-Agent', function () { $parser = new UserAgentParser(); $parsed = $parser->parse(''); expect($parsed->browser)->toBe(BrowserType::UNKNOWN); expect($parsed->browserVersion)->toBeInstanceOf(Version::class); expect($parsed->browserVersion->toString())->toBe('0.0.0'); expect($parsed->platform)->toBe(PlatformType::UNKNOWN); expect($parsed->engine)->toBe(EngineType::UNKNOWN); }); it('caches parsed user agents using Hash VO with fast algorithm', function () { // Note: UserAgentParser uses Hash::create($userAgent, HashAlgorithm::fast()) // This test verifies the caching behavior without relying on specific cache implementations $parser1 = new UserAgentParser(); $parser2 = new UserAgentParser(); $ua = 'Mozilla/5.0 (Windows NT 10.0) Chrome/120.0.0.0'; // Parse without cache $parsed1 = $parser1->parse($ua); $parsed2 = $parser2->parse($ua); // Both should produce identical results expect($parsed1->browser)->toBe($parsed2->browser); expect($parsed1->browserVersion->toString())->toBe($parsed2->browserVersion->toString()); // Verify Hash VO is used in cache key (integration point) // The actual cache key is: 'useragent:' . Hash::create($userAgent, HashAlgorithm::fast())->toString() $hash = \App\Framework\Core\ValueObjects\Hash::create( trim($ua), \App\Framework\Core\ValueObjects\HashAlgorithm::fast() ); expect($hash->toString())->toBeString(); expect(strlen($hash->toString()))->toBeGreaterThan(0); expect($hash->getAlgorithm())->toBeInstanceOf(\App\Framework\Core\ValueObjects\HashAlgorithm::class); }); it('determines modern browser correctly using Version comparison', function () { $parser = new UserAgentParser(); // Modern Chrome $modernChrome = $parser->parse('Mozilla/5.0 Chrome/120.0.0.0'); expect($modernChrome->isModern)->toBeTrue(); // Old Chrome (below threshold) $oldChrome = $parser->parse('Mozilla/5.0 Chrome/50.0.0.0'); expect($oldChrome->isModern)->toBeFalse(); }); it('parses version strings into Version value objects correctly', function () { $parser = new UserAgentParser(); $ua = 'Mozilla/5.0 Chrome/120.5.3'; $parsed = $parser->parse($ua); expect($parsed->browserVersion)->toBeInstanceOf(Version::class); expect($parsed->browserVersion->getMajor())->toBe(120); expect($parsed->browserVersion->getMinor())->toBe(5); expect($parsed->browserVersion->getPatch())->toBe(3); }); it('handles malformed version strings gracefully', function () { $parser = new UserAgentParser(); // Version with only major $ua1 = $parser->parse('Mozilla/5.0 Chrome/120'); expect($ua1->browserVersion)->toBeInstanceOf(Version::class); expect($ua1->browserVersion->getMajor())->toBe(120); // Version with major.minor $ua2 = $parser->parse('Mozilla/5.0 Chrome/120.5'); expect($ua2->browserVersion->getMajor())->toBe(120); expect($ua2->browserVersion->getMinor())->toBe(5); }); it('provides parser statistics', function () { $parser = new UserAgentParser(); $stats = $parser->getStats(); expect($stats)->toHaveKey('cacheEnabled'); expect($stats)->toHaveKey('supportedBrowsers'); expect($stats)->toHaveKey('supportedPlatforms'); expect($stats)->toHaveKey('supportedEngines'); expect($stats['cacheEnabled'])->toBeFalse(); expect($stats['supportedBrowsers'])->toBeGreaterThan(0); }); });