Passed
Pull Request — 1.x (#3)
by Kevin
02:01
created

HasBrowser::pantherBrowser()   A

Complexity

Conditions 4
Paths 1

Size

Total Lines 30
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 16
nc 1
nop 0
dl 0
loc 30
rs 9.7333
c 0
b 0
f 0
1
<?php
2
3
namespace Zenstruck\Browser\Test;
4
5
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
6
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
7
use Symfony\Component\BrowserKit\HttpBrowser as HttpBrowserClient;
8
use Symfony\Component\Panther\Client as PantherClient;
9
use Symfony\Component\Panther\PantherTestCase;
10
use Zenstruck\Browser\HttpBrowser;
11
use Zenstruck\Browser\KernelBrowser;
12
use Zenstruck\Browser\PantherBrowser;
13
14
/**
15
 * @author Kevin Bond <[email protected]>
16
 */
17
trait HasBrowser
18
{
19
    /** @var HttpBrowserClient[] */
20
    private static array $httpBrowserClients = [];
21
    private static ?PantherClient $primaryPantherClient = null;
22
23
    /**
24
     * @internal
25
     * @after
26
     */
27
    public static function _resetBrowserClients(): void
28
    {
29
        self::$httpBrowserClients = [];
30
        self::$primaryPantherClient = null;
31
    }
32
33
    final protected function pantherBrowser(): PantherBrowser
34
    {
35
        $browser = PantherBrowser::create(function() {
36
            if (!$this instanceof PantherTestCase) {
37
                throw new \RuntimeException(\sprintf('The "%s" method can only be used on TestCases that extend "%s".', __METHOD__, PantherTestCase::class));
38
            }
39
40
            $class = $_SERVER['PANTHER_BROWSER_CLASS'] ?? PantherBrowser::class;
41
42
            if (!\is_a($class, PantherBrowser::class, true)) {
43
                throw new \RuntimeException(\sprintf('"PANTHER_BROWSER_CLASS" env variable must reference a class that extends %s.', PantherBrowser::class));
44
            }
45
46
            if (self::$primaryPantherClient) {
47
                return new $class(static::createAdditionalPantherClient());
48
            }
49
50
            self::$primaryPantherClient = static::createPantherClient(
51
                ['browser' => $_SERVER['PANTHER_BROWSER'] ?? static::CHROME]
0 ignored issues
show
Bug introduced by
The constant Zenstruck\Browser\Test\HasBrowser::CHROME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
52
            );
53
54
            return new $class(self::$primaryPantherClient);
55
        });
56
57
        BrowserExtension::registerBrowser($browser);
58
59
        return $browser
60
            ->setSourceDir($_SERVER['BROWSER_SOURCE_DIR'] ?? './var/browser/source')
61
            ->setScreenshotDir($_SERVER['BROWSER_SCREENSHOT_DIR'] ?? './var/browser/screenshots')
62
            ->setConsoleLogDir($_SERVER['BROWSER_CONSOLE_LOG_DIR'] ?? './var/browser/console-logs')
63
        ;
64
    }
65
66
    final protected function httpBrowser(): HttpBrowser
67
    {
68
        $browser = HttpBrowser::create(function() {
69
            $class = $_SERVER['HTTP_BROWSER_CLASS'] ?? HttpBrowser::class;
70
71
            if (!\is_a($class, HttpBrowser::class, true)) {
72
                throw new \RuntimeException(\sprintf('"HTTP_BROWSER_CLASS" env variable must reference a class that extends %s.', HttpBrowser::class));
73
            }
74
75
            $baseUri = $_SERVER['HTTP_BROWSER_URI'] ?? null;
76
77
            if (!$baseUri && !$this instanceof PantherTestCase) {
78
                throw new \RuntimeException(\sprintf('If not using "HTTP_BROWSER_URI", your TestCase must extend "%s".', PantherTestCase::class));
79
            }
80
81
            if (!$baseUri) {
82
                self::startWebServer();
83
84
                $baseUri = self::$baseUri;
85
            }
86
87
            // copied from PantherTestCaseTrait::createHttpBrowserClient()
88
            $client = new HttpBrowserClient();
89
            $urlComponents = \parse_url($baseUri);
90
            $host = $urlComponents['host'];
91
92
            if (isset($urlComponents['port'])) {
93
                $host .= ":{$urlComponents['port']}";
94
            }
95
96
            $client->setServerParameter('HTTP_HOST', $host);
97
98
            if ('https' === ($urlComponents['scheme'] ?? 'http')) {
99
                $client->setServerParameter('HTTPS', 'true');
100
            }
101
102
            /** @var HttpBrowser $browser */
103
            $browser = $class(self::$httpBrowserClients[] = $client);
104
105
            if (!$this instanceof KernelTestCase) {
106
                $this->configureBrowser($browser);
0 ignored issues
show
Bug introduced by
It seems like configureBrowser() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

106
                $this->/** @scrutinizer ignore-call */ 
107
                       configureBrowser($browser);
Loading history...
107
108
                return $browser;
109
            }
110
111
            if (!static::$booted) {
0 ignored issues
show
Bug introduced by
The property booted is declared protected in Symfony\Bundle\FrameworkBundle\Test\KernelTestCase and cannot be accessed from this context.
Loading history...
112
                static::bootKernel();
113
            }
114
115
            if (static::$container->has('profiler')) {
0 ignored issues
show
Bug introduced by
The property container is declared protected in Symfony\Bundle\FrameworkBundle\Test\KernelTestCase and cannot be accessed from this context.
Loading history...
116
                $browser->setProfiler(static::$container->get('profiler'));
0 ignored issues
show
Bug introduced by
It seems like static::container->get('profiler') can also be of type null; however, parameter $profiler of Zenstruck\Browser\HttpBrowser::setProfiler() does only seem to accept Symfony\Component\HttpKernel\Profiler\Profiler, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

116
                $browser->setProfiler(/** @scrutinizer ignore-type */ static::$container->get('profiler'));
Loading history...
117
            }
118
119
            return $browser;
120
        });
121
122
        BrowserExtension::registerBrowser($browser);
123
124
        return $browser
125
            ->setSourceDir($_SERVER['BROWSER_SOURCE_DIR'] ?? './var/browser/source')
126
        ;
127
    }
128
129
    final protected function browser(): KernelBrowser
130
    {
131
        if (!$this instanceof KernelTestCase) {
132
            throw new \RuntimeException(\sprintf('The "%s" method can only be used on TestCases that extend "%s".', __METHOD__, KernelTestCase::class));
133
        }
134
135
        $browser = KernelBrowser::create(function() {
136
            $class = $_SERVER['KERNEL_BROWSER_CLASS'] ?? KernelBrowser::class;
137
138
            if (!\is_a($class, KernelBrowser::class, true)) {
139
                throw new \RuntimeException(\sprintf('"KERNEL_BROWSER_CLASS" env variable must reference a class that extends %s.', KernelBrowser::class));
140
            }
141
142
            if ($this instanceof WebTestCase) {
143
                static::ensureKernelShutdown();
144
145
                return new $class(static::createClient());
146
            }
147
148
            // reboot kernel before starting browser
149
            static::bootKernel();
150
151
            if (!static::$container->has('test.client')) {
152
                throw new \RuntimeException('The Symfony test client is not enabled.');
153
            }
154
155
            return new $class(static::$container->get('test.client'));
156
        });
157
158
        BrowserExtension::registerBrowser($browser);
159
160
        return $browser
161
            ->setSourceDir($_SERVER['BROWSER_SOURCE_DIR'] ?? './var/browser/source')
162
        ;
163
    }
164
}
165