Skip to content

Refactor CookieSetter to optimize browser navigation#18447

Merged
Rafikooo merged 1 commit intoSylius:2.1from
Rafikooo:cookie-setter-improvement
Nov 2, 2025
Merged

Refactor CookieSetter to optimize browser navigation#18447
Rafikooo merged 1 commit intoSylius:2.1from
Rafikooo:cookie-setter-improvement

Conversation

@Rafikooo
Copy link
Copy Markdown
Contributor

@Rafikooo Rafikooo commented Oct 17, 2025

Summary

Optimized cookie setter to avoid unnecessary page navigations in Behat tests

Before: ChromeDriver and Selenium2Driver always required visiting base_url before setting cookies, even when already on a valid page.

After: Smart detection checks current URL state - only visits base_url when truly needed (blank page states).

Summary by CodeRabbit

  • Refactor
    • Improved automated testing reliability by strengthening cookie handling and browser session startup logic.
    • Added stricter typing and safety checks to test helpers to reduce flaky test runs.
    • Better detection of unloaded pages to ensure tests run against initialized browser sessions.

@Rafikooo Rafikooo requested review from a team as code owners October 17, 2025 12:45
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 17, 2025

Walkthrough

CookieSetter is now a readonly class with constructor property promotion and a typed setCookie(string $name, string $value): void. Driver startup logic was extracted to ensureDriverStarted(). Mink session preparation and page-load checks were refined via shouldMinkSessionBePrepared() and isPageNotLoaded(). SymfonyDriver cookie handling now builds a Cookie with host derived from base_url.

Changes

Cohort / File(s) Summary
Cookie Setter & Interface
src/Sylius/Behat/Service/Setter/CookieSetter.php, src/Sylius/Behat/Service/Setter/CookieSetterInterface.php
CookieSetter declared readonly with constructor property promotion. setCookie signature changed to public function setCookie(string $name, string $value): void (interface updated). Introduced ensureDriverStarted(mixed $driver): void, isPageNotLoaded(string $url): bool, and refined shouldMinkSessionBePrepared() logic. Deferred Mink session preparation; SymfonyDriver path now constructs a Cookie using host derived from base_url.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant CookieSetter
    participant Driver
    participant MinkSession
    participant CookieJar

    Caller->>CookieSetter: setCookie(name, value)

    rect rgb(245,245,255)
    Note over CookieSetter: ensureDriverStarted(driver)
    CookieSetter->>Driver: ensureDriverStarted(mixed driver)
    alt ChromeDriver / PantherDriver
        Driver-->>CookieSetter: start if needed
    else Other drivers
        Driver-->>CookieSetter: no-op/start not needed
    end
    end

    rect rgb(245,255,245)
    Note over CookieSetter: prepare session & set cookie
    alt SymfonyDriver
        CookieSetter->>CookieJar: create cookie (host from base_url)
        CookieSetter->>CookieJar: add cookie
    else Other drivers
        CookieSetter->>CookieSetter: prepareMinkSessionIfNeeded()
        CookieSetter->>MinkSession: set cookie in session
    end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to: ensureDriverStarted() behavior for ChromeDriver vs PantherDriver, shouldMinkSessionBePrepared() branching (Selenium2Driver vs ChromeDriver vs others), and SymfonyDriver cookie host derivation from base_url.

Poem

🐰 I nudged the driver, woke it slow,
Promoted props in morning glow,
Typed the name and tucked the treat,
Host set right — the cookie’s neat,
A tiny hop — the tests will show. 🍪🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Refactor CookieSetter to optimize browser navigation" is fully related to and accurately summarizes the main change in this pull request. The changeset includes refactoring work on the CookieSetter class (making it readonly, adding promoted properties, introducing helper methods like ensureDriverStarted and isPageNotLoaded) with the primary goal of optimizing browser navigation by implementing smart URL state detection. This prevents unnecessary page navigations to base_url when the browser is already on a valid page. The title is concise, clear, and specific enough that a teammate reviewing the PR history would understand the primary intent without being overly detailed or vague.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Oct 17, 2025

❌ Preview Environment deleted from Bunnyshell

Available commands:

  • 🚀 /bns:deploy to redeploy the environment

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Sylius/Behat/Service/Setter/CookieSetter.php (1)

49-54: Tighten the parameter type for ensureDriverStarted.

Using mixed is unnecessarily broad. Prefer DriverInterface to reflect actual usage and intent. Also add the missing import (keeps use list alphabetized).

+use Behat\Mink\Driver\DriverInterface;
@@
-    private function ensureDriverStarted(mixed $driver): void
+    private function ensureDriverStarted(DriverInterface $driver): void
     {
         if (($driver instanceof ChromeDriver || $driver instanceof PantherDriver) && !$driver->isStarted()) {
             $driver->start();
         }
     }

As per coding guidelines.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf36bcc and 68d725f.

📒 Files selected for processing (2)
  • src/Sylius/Behat/Service/Setter/CookieSetter.php (3 hunks)
  • src/Sylius/Behat/Service/Setter/CookieSetterInterface.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{php,yaml,yml,xml,twig}

📄 CodeRabbit inference engine (AGENTS.md)

Use 4 spaces for indentation in PHP, YAML, XML, and Twig files

Files:

  • src/Sylius/Behat/Service/Setter/CookieSetterInterface.php
  • src/Sylius/Behat/Service/Setter/CookieSetter.php
**/*.php

📄 CodeRabbit inference engine (AGENTS.md)

**/*.php: Use modern PHP 8.2+ syntax and features
Declare strict_types=1 in all PHP files
Follow the Sylius Coding Standard
Do not use deprecated features from PHP, Symfony, or Sylius
Use final for all classes, except entities and repositories
Use readonly for immutable services and value objects
Add type declarations for all properties, arguments, and return values
Use camelCase for variables and method names
Use SCREAMING_SNAKE_CASE for constants
Use fast returns instead of unnecessary nesting
Use trailing commas in multi-line arrays and argument lists
Order array keys alphabetically where applicable
Use PHPDoc only when necessary (e.g., @var Collection)
Group class elements in order: constants, properties, constructor, public, protected, private methods
Group getter and setter methods for the same properties together
Suffix interfaces with Interface and traits with Trait
Use use statements for all non-global classes
Sort use imports alphabetically and group by type (classes, functions, constants)

Files:

  • src/Sylius/Behat/Service/Setter/CookieSetterInterface.php
  • src/Sylius/Behat/Service/Setter/CookieSetter.php
🧬 Code graph analysis (2)
src/Sylius/Behat/Service/Setter/CookieSetterInterface.php (1)
src/Sylius/Behat/Service/Setter/CookieSetter.php (1)
  • setCookie (31-47)
src/Sylius/Behat/Service/Setter/CookieSetter.php (1)
src/Sylius/Behat/Service/Setter/CookieSetterInterface.php (1)
  • setCookie (18-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: End-to-end tests (MariaDB) / Get matrix
  • GitHub Check: End-to-end tests (PostgreSQL) / Get matrix
🔇 Additional comments (4)
src/Sylius/Behat/Service/Setter/CookieSetter.php (3)

23-23: Good: final readonly service.

Matches immutability guidance and narrows surface area.


31-47: Solid restructuring; two small verifications.

  • Early return for SymfonyDriver + deferred session prep = good.
  • Verify minkParameters always contains a valid base_url; otherwise accessing $this->minkParameters['base_url'] may notice/throw under ArrayAccess. Consider guarding or asserting.
  • For SymfonyDriver domain, parse_url(..., PHP_URL_HOST) is appropriate; please confirm expected behavior for IPv6/localhost deployments.

82-85: Blank-page detection LGTM; confirm driver variants.

Covers '', about:blank, data:,. If you see other initial URLs (e.g., chrome’s new-tab), extend here.

src/Sylius/Behat/Service/Setter/CookieSetterInterface.php (1)

18-18: Interface signature verified with matching implementation.

All implementers are compliant. The single implementation in CookieSetter.php:31 matches the typed interface signature exactly, adhering to strict typing and void return guidelines.

Comment on lines +71 to +80
if ($driver instanceof Selenium2Driver) {
return $driver->getWebDriverSession() === null || $this->isPageNotLoaded($session->getCurrentUrl());
}

if ($driver instanceof ChromeDriver) {
return true;
return $this->isPageNotLoaded($session->getCurrentUrl());
}

if (str_contains($session->getCurrentUrl(), $this->minkParameters['base_url'])) {
return false;
}
return !str_contains($session->getCurrentUrl(), $this->minkParameters['base_url']);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix false-positive base_url detection for “other” drivers.

Using str_contains can match unrelated domains (e.g., http://shop in http://shopper.example.com), causing skipped preparation. Prefer a prefix match on normalized base_url and also treat “blank” pages as not loaded.

-        return !str_contains($session->getCurrentUrl(), $this->minkParameters['base_url']);
+        return $this->isPageNotLoaded($session->getCurrentUrl())
+            || !str_starts_with(
+                $session->getCurrentUrl(),
+                rtrim($this->minkParameters['base_url'], '/') . '/'
+            );

If you prefer host-level certainty, compare hosts via parse_url.

@Rafikooo Rafikooo force-pushed the cookie-setter-improvement branch 2 times, most recently from 53f551c to 515b447 Compare October 21, 2025 11:26
Improved the cookie setter logic to avoid unnecessary page navigations:
- Extract driver start logic into ensureDriverStarted() method
- Unify page load detection for Selenium2Driver and ChromeDriver
- Skip base_url visit when page is already loaded (about:blank, data:,)
- Move prepareMinkSessionIfNeeded() after SymfonyDriver early return
- Add readonly modifier to class and type declarations to methods
- Simplify shouldMinkSessionBePrepared() logic with early returns
@Rafikooo Rafikooo force-pushed the cookie-setter-improvement branch from 515b447 to c8d0803 Compare October 29, 2025 10:51
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/Sylius/Behat/Service/Setter/CookieSetter.php (1)

71-80: Fix false-positive base_url detection for “other” drivers.

str_contains can match unrelated domains (e.g., http://shop in http://shopper.example.com), skipping required preparation and setting cookies on the wrong host. Use a prefix match on normalized base_url and also treat blank pages as not loaded.

-        return !str_contains($session->getCurrentUrl(), $this->minkParameters['base_url']);
+        return $this->isPageNotLoaded($session->getCurrentUrl())
+            || !str_starts_with(
+                $session->getCurrentUrl(),
+                rtrim((string) $this->minkParameters['base_url'], '/') . '/'
+            );

If you prefer host-level certainty:

$curr = parse_url($session->getCurrentUrl(), \PHP_URL_HOST);
$base = parse_url((string) $this->minkParameters['base_url'], \PHP_URL_HOST);
return $this->isPageNotLoaded($session->getCurrentUrl()) || ($curr !== $base);
🧹 Nitpick comments (3)
src/Sylius/Behat/Service/Setter/CookieSetter.php (3)

37-41: SymfonyDriver cookie: ensure host presence; consider explicit path.

parse_url may return null if base_url is misconfigured. Guard and default path to '/' to avoid ambiguity in BrowserKit.

-            $driver->getClient()->getCookieJar()->set(
-                new Cookie($name, $value, null, null, parse_url($this->minkParameters['base_url'], \PHP_URL_HOST)),
-            );
+            $host = parse_url((string) $this->minkParameters['base_url'], \PHP_URL_HOST);
+            if ($host === null) {
+                throw new \InvalidArgumentException('Parameter "base_url" must include a host to set cookies with SymfonyDriver.');
+            }
+            $driver->getClient()->getCookieJar()->set(
+                new Cookie($name, $value, null, '/', $host),
+            );

49-55: Narrow the type of ensureDriverStarted() to DriverInterface.

Use the interface returned by Session::getDriver() instead of mixed.

-    private function ensureDriverStarted(mixed $driver): void
+    private function ensureDriverStarted(DriverInterface $driver): void
     {
         if (($driver instanceof ChromeDriver || $driver instanceof PantherDriver) && !$driver->isStarted()) {
             $driver->start();
         }
     }

And add the import (kept alphabetical within Behat\Mink\Driver group):

-use Behat\Mink\Driver\PantherDriver;
+use Behat\Mink\Driver\DriverInterface;
+use Behat\Mink\Driver\PantherDriver;
 use Behat\Mink\Driver\Selenium2Driver;
 use Behat\Mink\Session;

82-85: Broaden “blank page” detection (optional).

Covers about:blank#blocked and trims whitespace; keeps current behavior for data:, and exact blank.

-    private function isPageNotLoaded(string $url): bool
-    {
-        return in_array($url, ['', 'about:blank', 'data:,'], true);
-    }
+    private function isPageNotLoaded(string $url): bool
+    {
+        $url = trim($url);
+        return $url === ''
+            || str_starts_with($url, 'about:blank')
+            || $url === 'data:,';
+    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 515b447 and c8d0803.

📒 Files selected for processing (2)
  • src/Sylius/Behat/Service/Setter/CookieSetter.php (3 hunks)
  • src/Sylius/Behat/Service/Setter/CookieSetterInterface.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Sylius/Behat/Service/Setter/CookieSetterInterface.php
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{php,yaml,yml,xml,twig}

📄 CodeRabbit inference engine (AGENTS.md)

Use 4 spaces for indentation in PHP, YAML, XML, and Twig files

Files:

  • src/Sylius/Behat/Service/Setter/CookieSetter.php
**/*.php

📄 CodeRabbit inference engine (AGENTS.md)

**/*.php: Use modern PHP 8.2+ syntax and features
Declare strict_types=1 in all PHP files
Follow the Sylius Coding Standard
Do not use deprecated features from PHP, Symfony, or Sylius
Use final for all classes, except entities and repositories
Use readonly for immutable services and value objects
Add type declarations for all properties, arguments, and return values
Use camelCase for variables and method names
Use SCREAMING_SNAKE_CASE for constants
Use fast returns instead of unnecessary nesting
Use trailing commas in multi-line arrays and argument lists
Order array keys alphabetically where applicable
Use PHPDoc only when necessary (e.g., @var Collection)
Group class elements in order: constants, properties, constructor, public, protected, private methods
Group getter and setter methods for the same properties together
Suffix interfaces with Interface and traits with Trait
Use use statements for all non-global classes
Sort use imports alphabetically and group by type (classes, functions, constants)

Files:

  • src/Sylius/Behat/Service/Setter/CookieSetter.php
🧬 Code graph analysis (1)
src/Sylius/Behat/Service/Setter/CookieSetter.php (1)
src/Sylius/Behat/Service/Setter/CookieSetterInterface.php (1)
  • setCookie (18-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Frontend / Get matrix
  • GitHub Check: Packages / Get matrix
  • GitHub Check: End-to-end tests (MariaDB) / Get matrix
  • GitHub Check: End-to-end tests (PostgreSQL) / Get matrix
  • GitHub Check: End-to-end tests (MySQL) / Get matrix
🔇 Additional comments (2)
src/Sylius/Behat/Service/Setter/CookieSetter.php (2)

23-23: Good modernization: final + readonly.

Matches the guidelines for immutable services and class finality.


31-31: Correct call order: start driver, then conditionally prepare session.

This prevents unnecessary navigations while ensuring cookie APIs have a valid context.

Also applies to: 35-36, 45-46

@Rafikooo Rafikooo merged commit 19edffd into Sylius:2.1 Nov 2, 2025
48 of 49 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants