diff --git a/src/Driver/ChromeDriver/VersionResolver.php b/src/Driver/ChromeDriver/VersionResolver.php index 92f0461..ae974d5 100644 --- a/src/Driver/ChromeDriver/VersionResolver.php +++ b/src/Driver/ChromeDriver/VersionResolver.php @@ -23,7 +23,8 @@ final class VersionResolver implements VersionResolverInterface { public const MAJOR_VERSION_ENDPOINT_BREAKPOINT = 115; - private const VERSION_ENDPOINT = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE'; + private const LEGACY_ENDPOINT = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE'; + private const LATEST_VERSION_ENDPOINT_JSON = 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json'; private const VERSION_ENDPOINT_JSON = 'https://googlechromelabs.github.io/chrome-for-testing/latest-patch-versions-per-build.json'; private HttpClientInterface $httpClient; @@ -68,10 +69,13 @@ public function fromBrowser(Browser $browser): Version public function latest(): Version { - $response = $this->httpClient->request('GET', self::VERSION_ENDPOINT); - $versionString = $response->getContent(); + $response = $this->httpClient->request('GET', self::LATEST_VERSION_ENDPOINT_JSON); + $versions = $response->toArray(); + if (! isset($versions['channels']['Stable']['version'])) { + throw new UnexpectedValueException('Could not resolve the latest stable version.'); + } - return Version::fromString($versionString); + return Version::fromString((string) $versions['channels']['Stable']['version']); } public function supports(Browser $browser): bool @@ -81,6 +85,17 @@ public function supports(Browser $browser): bool return $browserName->equals(BrowserName::GOOGLE_CHROME()) || $browserName->equals(BrowserName::CHROMIUM()); } + private function latestBetaVersion(): Version + { + $response = $this->httpClient->request('GET', self::LATEST_VERSION_ENDPOINT_JSON); + $versions = $response->toArray(); + if (! isset($versions['channels']['Beta']['version'])) { + throw new UnexpectedValueException('Could not resolve the latest beta version.'); + } + + return Version::fromString((string) $versions['channels']['Beta']['version']); + } + /** * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface @@ -95,13 +110,21 @@ private function getVersionString(Browser $browser): string $response = $this->httpClient->request('GET', self::VERSION_ENDPOINT_JSON); $versions = $response->toArray(); - if (! array_key_exists($browser->version()->toString(), $versions['builds'])) { + + $latestBeta = $this->latestBetaVersion(); + $versionToFetch = $browser->version(); + if ((int) $versionToFetch->major() > (int) $latestBeta->major()) { + // In this case we're dealing with a Dev or Canary version, so we will take the last Beta version. + $versionToFetch = $latestBeta; + } + + if (! array_key_exists($versionToFetch->toString(), $versions['builds'])) { throw new UnexpectedValueException( - sprintf('There is no build for version : %s', $browser->version()->toString()) + sprintf('There is no build for version : %s', $versionToFetch->toString()) ); } - return $versions['builds'][$browser->version()->toString()]['version']; + return $versions['builds'][$versionToFetch->toString()]['version']; } /** @@ -109,13 +132,13 @@ private function getVersionString(Browser $browser): string */ private function getBrowserVersionEndpoint(Browser $browser): string { - $versionEndpoint = sprintf('%s_%s', self::VERSION_ENDPOINT, $browser->version()->toString()); + $versionEndpoint = sprintf('%s_%s', self::LEGACY_ENDPOINT, $browser->version()->toString()); $stableVersion = $this->latest(); $betaVersionMajor = (int) $stableVersion->major() + 1; if ((int) $browser->version()->major() > $betaVersionMajor) { - $versionEndpoint = sprintf('%s_%s', self::VERSION_ENDPOINT, (string) $betaVersionMajor); + $versionEndpoint = sprintf('%s_%s', self::LEGACY_ENDPOINT, (string) $betaVersionMajor); } return $versionEndpoint; diff --git a/tests/Driver/ChromeDriver/VersionResolverTest.php b/tests/Driver/ChromeDriver/VersionResolverTest.php index 6aa3d2e..6e68fed 100644 --- a/tests/Driver/ChromeDriver/VersionResolverTest.php +++ b/tests/Driver/ChromeDriver/VersionResolverTest.php @@ -71,14 +71,14 @@ public function testFromExceptionIfCanNotParseVersionReceived(): void public function testFromGetBetaVersionForDevChrome(): void { - $devChrome = new Browser(BrowserName::GOOGLE_CHROME(), Version::fromString('88.0.4302.0'), OperatingSystem::MACOS()); + $devChrome = new Browser(BrowserName::GOOGLE_CHROME(), Version::fromString('123.0.6300.3'), OperatingSystem::MACOS()); - self::assertEquals(Version::fromString('87.0.4280.20'), $this->versionResolver->fromBrowser($devChrome)); + self::assertEquals(Version::fromString('122.0.6261.39'), $this->versionResolver->fromBrowser($devChrome)); } public function testLatest(): void { - self::assertEquals(Version::fromString('86.0.4240.22'), $this->versionResolver->latest()); + self::assertEquals(Version::fromString('121.0.6167.184'), $this->versionResolver->latest()); } protected function setUp(): void @@ -99,9 +99,25 @@ static function (string $method, string $url): MockResponse { return new MockResponse('87.0.4280.20'); } + if ($url === 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json') { + return new MockResponse( + json_encode([ + 'channels' => [ + 'Stable' => ['version' => '121.0.6167.184'], + 'Beta' => ['version' => '122.0.6261.39'], + ], + ]) + ); + } + if ($url === 'https://googlechromelabs.github.io/chrome-for-testing/latest-patch-versions-per-build.json') { return new MockResponse( - json_encode(['builds' => ['115.0.5751' => ['version' => '115.0.5751.20']]]) + json_encode([ + 'builds' => [ + '115.0.5751' => ['version' => '115.0.5751.20'], + '122.0.6261' => ['version' => '122.0.6261.39'], + ], + ]) ); } }