From f9b436a796c3b222cd16bd334dd848c564ce7c7f Mon Sep 17 00:00:00 2001 From: awu Date: Wed, 1 Oct 2025 14:05:53 +0200 Subject: [PATCH 1/5] feat: add dynamic port resolution for WaitForHttp --- src/Wait/WaitForHttp.php | 5 ++++- tests/Integration/GenericContainerTest.php | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Wait/WaitForHttp.php b/src/Wait/WaitForHttp.php index 855c55f..d5c2c03 100644 --- a/src/Wait/WaitForHttp.php +++ b/src/Wait/WaitForHttp.php @@ -104,7 +104,10 @@ public function wait(StartedTestContainer $container): void $this->resolvePort($container); $containerAddress = $container->getHost(); - $url = sprintf('%s://%s:%d%s', $this->protocol, $containerAddress, $this->port, $this->path); + $storage = iterator_to_array($container->getBoundPorts()); + $port = array_key_exists($this->port . '/tcp', $storage) ? $storage[$this->port . '/tcp'][0]->getHostPort() : $this->port; + + $url = sprintf('%s://%s:%d%s', $this->protocol, $containerAddress, $port, $this->path); $responseCode = $this->makeHttpRequest($url); if ($responseCode === $this->expectedStatusCode) { diff --git a/tests/Integration/GenericContainerTest.php b/tests/Integration/GenericContainerTest.php index 7ed65bb..b45b63b 100644 --- a/tests/Integration/GenericContainerTest.php +++ b/tests/Integration/GenericContainerTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\TestCase; use Testcontainers\Container\GenericContainer; use Testcontainers\Wait\WaitForHostPort; +use Testcontainers\Wait\WaitForHttp; class GenericContainerTest extends TestCase { @@ -111,7 +112,7 @@ public function testShouldCopyFileWithPermissions(): void $container->stop(); } - public function testShouldReturnFirstMappedPort(): void + public function testShouldReturnFirstMappedPortWithWaitForHostPort(): void { $container = (new GenericContainer('nginx')) ->withExposedPorts(80) @@ -124,6 +125,19 @@ public function testShouldReturnFirstMappedPort(): void $container->stop(); } + public function testShouldReturnFirstMappedPortWithWaitForHttp(): void + { + $container = (new GenericContainer('nginx')) + ->withExposedPorts(80) + ->withWait((new WaitForHttp(80))->withPath('/')) + ->start(); + $firstMappedPort = $container->getFirstMappedPort(); + + self::assertSame($firstMappedPort, $container->getMappedPort(80)); + + $container->stop(); + } + public function testShouldSetLabels(): void { $labels = [ From 74f1d3a04638c2dffe4c8d6162ef22ea4bbec850 Mon Sep 17 00:00:00 2001 From: awu Date: Wed, 1 Oct 2025 14:26:38 +0200 Subject: [PATCH 2/5] feat: add dynamic port resolution for WaitForHttp --- src/Wait/WaitForHttp.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Wait/WaitForHttp.php b/src/Wait/WaitForHttp.php index d5c2c03..dbcbb81 100644 --- a/src/Wait/WaitForHttp.php +++ b/src/Wait/WaitForHttp.php @@ -104,10 +104,7 @@ public function wait(StartedTestContainer $container): void $this->resolvePort($container); $containerAddress = $container->getHost(); - $storage = iterator_to_array($container->getBoundPorts()); - $port = array_key_exists($this->port . '/tcp', $storage) ? $storage[$this->port . '/tcp'][0]->getHostPort() : $this->port; - - $url = sprintf('%s://%s:%d%s', $this->protocol, $containerAddress, $port, $this->path); + $url = sprintf('%s://%s:%d%s', $this->protocol, $containerAddress, $container->getMappedPort($this->port), $this->path); $responseCode = $this->makeHttpRequest($url); if ($responseCode === $this->expectedStatusCode) { From 6dbab2f3373b4363f275d5ab6dd4f68a6f8c05ba Mon Sep 17 00:00:00 2001 From: awu Date: Wed, 1 Oct 2025 16:21:48 +0200 Subject: [PATCH 3/5] chore: simplify WaitForHttp usage in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cf82ac9..734dbe6 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ $container->withWait(new WaitForLog('Ready to accept connections')); // Wait for an http request to succeed -$container->withWait(new WaitForHttp($port, $method = 'GET', $path = '/')); +$container->withWait((new WaitForHttp($port))->withMethod('GET')->withPath('/')); // Wait for all bound ports to be open $container->withWait(new WaitForHostPort()); From f5718c935f17b19deafbe882c0136f764ba7f734 Mon Sep 17 00:00:00 2001 From: awu Date: Wed, 1 Oct 2025 17:01:38 +0200 Subject: [PATCH 4/5] fix: phpstan adjustment for cast to int in WaitForHttp and sanitize output --- src/Container/StartedGenericContainer.php | 3 +++ src/Wait/WaitForHttp.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Container/StartedGenericContainer.php b/src/Container/StartedGenericContainer.php index 13493dd..2f443ec 100644 --- a/src/Container/StartedGenericContainer.php +++ b/src/Container/StartedGenericContainer.php @@ -98,6 +98,9 @@ public function logs(): string ?->getBody() ->getContents() ?? ''; + /** + * @var string|false $converted + */ $converted = mb_convert_encoding($output, 'UTF-8', 'UTF-8'); return $this->sanitizeOutput($converted === false ? $output : $converted); } diff --git a/src/Wait/WaitForHttp.php b/src/Wait/WaitForHttp.php index dbcbb81..d9aa521 100644 --- a/src/Wait/WaitForHttp.php +++ b/src/Wait/WaitForHttp.php @@ -104,7 +104,7 @@ public function wait(StartedTestContainer $container): void $this->resolvePort($container); $containerAddress = $container->getHost(); - $url = sprintf('%s://%s:%d%s', $this->protocol, $containerAddress, $container->getMappedPort($this->port), $this->path); + $url = sprintf('%s://%s:%d%s', $this->protocol, $containerAddress, $container->getMappedPort((int) $this->port), $this->path); $responseCode = $this->makeHttpRequest($url); if ($responseCode === $this->expectedStatusCode) { From e4aee91819140d9ae38cda815d3d73273a86c1f6 Mon Sep 17 00:00:00 2001 From: awu Date: Fri, 17 Oct 2025 09:06:40 +0200 Subject: [PATCH 5/5] fix: correct port handling in WaitForHttp and enhance test coverage --- src/Wait/WaitForHttp.php | 8 ++++---- tests/Integration/GenericContainerTest.php | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Wait/WaitForHttp.php b/src/Wait/WaitForHttp.php index d9aa521..31d4c08 100644 --- a/src/Wait/WaitForHttp.php +++ b/src/Wait/WaitForHttp.php @@ -104,7 +104,7 @@ public function wait(StartedTestContainer $container): void $this->resolvePort($container); $containerAddress = $container->getHost(); - $url = sprintf('%s://%s:%d%s', $this->protocol, $containerAddress, $container->getMappedPort((int) $this->port), $this->path); + $url = sprintf('%s://%s:%d%s', $this->protocol, $containerAddress, $this->port, $this->path); $responseCode = $this->makeHttpRequest($url); if ($responseCode === $this->expectedStatusCode) { @@ -147,8 +147,8 @@ private function makeHttpRequest(string $url): int private function resolvePort(StartedTestContainer $container): void { - if ($this->port === null) { - $this->port = $container->getFirstMappedPort(); - } + $this->port = $this->port === null + ? $container->getFirstMappedPort() + : $container->getMappedPort($this->port); } } diff --git a/tests/Integration/GenericContainerTest.php b/tests/Integration/GenericContainerTest.php index b45b63b..0b4188f 100644 --- a/tests/Integration/GenericContainerTest.php +++ b/tests/Integration/GenericContainerTest.php @@ -129,7 +129,7 @@ public function testShouldReturnFirstMappedPortWithWaitForHttp(): void { $container = (new GenericContainer('nginx')) ->withExposedPorts(80) - ->withWait((new WaitForHttp(80))->withPath('/')) + ->withWait((new WaitForHttp())->withMethod('GET')->withPath('/')) ->start(); $firstMappedPort = $container->getFirstMappedPort(); @@ -138,6 +138,19 @@ public function testShouldReturnFirstMappedPortWithWaitForHttp(): void $container->stop(); } + public function testShouldReturnMappedPortWithWaitForHttp(): void + { + $container = (new GenericContainer('nginx')) + ->withExposedPorts(80) + ->withWait((new WaitForHttp(80))->withMethod('GET')->withPath('/')) + ->start(); + $mappedPort = $container->getMappedPort(80); + + self::assertSame($mappedPort, $container->getFirstMappedPort()); + + $container->stop(); + } + public function testShouldSetLabels(): void { $labels = [