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

HasBrowser   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 21
eloc 67
c 4
b 0
f 0
dl 0
loc 152
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A _configurePHPUnitAssertionHandler() 0 3 1
B httpBrowser() 0 58 10
A pantherBrowser() 0 30 4
A _resetBrowserClients() 0 4 1
A kernelBrowser() 0 33 5
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\Assert;
11
use Zenstruck\Browser\Assert\Handler\PHPUnitHandler;
12
use Zenstruck\Browser\HttpBrowser;
13
use Zenstruck\Browser\KernelBrowser;
14
use Zenstruck\Browser\PantherBrowser;
15
16
/**
17
 * @author Kevin Bond <[email protected]>
18
 */
19
trait HasBrowser
20
{
21
    /** @var HttpBrowserClient[] */
22
    private static array $httpBrowserClients = [];
23
    private static ?PantherClient $primaryPantherClient = null;
24
25
    /**
26
     * @internal
27
     * @after
28
     */
29
    final public static function _resetBrowserClients(): void
30
    {
31
        self::$httpBrowserClients = [];
32
        self::$primaryPantherClient = null;
33
    }
34
35
    /**
36
     * @internal
37
     * @beforeClass
38
     */
39
    final public static function _configurePHPUnitAssertionHandler(): void
40
    {
41
        Assert::setHandler(new PHPUnitHandler());
42
    }
43
44
    protected function pantherBrowser(): PantherBrowser
45
    {
46
        $browser = PantherBrowser::create(function() {
47
            if (!$this instanceof PantherTestCase) {
48
                throw new \RuntimeException(\sprintf('The "%s" method can only be used on TestCases that extend "%s".', __METHOD__, PantherTestCase::class));
49
            }
50
51
            $class = $_SERVER['PANTHER_BROWSER_CLASS'] ?? PantherBrowser::class;
52
53
            if (!\is_a($class, PantherBrowser::class, true)) {
54
                throw new \RuntimeException(\sprintf('"PANTHER_BROWSER_CLASS" env variable must reference a class that extends %s.', PantherBrowser::class));
55
            }
56
57
            if (self::$primaryPantherClient) {
58
                return new $class(static::createAdditionalPantherClient());
59
            }
60
61
            self::$primaryPantherClient = static::createPantherClient(
62
                ['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...
63
            );
64
65
            return new $class(self::$primaryPantherClient);
66
        });
67
68
        BrowserExtension::registerBrowser($browser);
69
70
        return $browser
71
            ->setSourceDir($_SERVER['BROWSER_SOURCE_DIR'] ?? './var/browser/source')
72
            ->setScreenshotDir($_SERVER['BROWSER_SCREENSHOT_DIR'] ?? './var/browser/screenshots')
73
            ->setConsoleLogDir($_SERVER['BROWSER_CONSOLE_LOG_DIR'] ?? './var/browser/console-logs')
74
        ;
75
    }
76
77
    protected function httpBrowser(): HttpBrowser
78
    {
79
        $browser = HttpBrowser::create(function() {
80
            $class = $_SERVER['HTTP_BROWSER_CLASS'] ?? HttpBrowser::class;
81
82
            if (!\is_a($class, HttpBrowser::class, true)) {
83
                throw new \RuntimeException(\sprintf('"HTTP_BROWSER_CLASS" env variable must reference a class that extends %s.', HttpBrowser::class));
84
            }
85
86
            $baseUri = $_SERVER['HTTP_BROWSER_URI'] ?? null;
87
88
            if (!$baseUri && !$this instanceof PantherTestCase) {
89
                throw new \RuntimeException(\sprintf('If not using "HTTP_BROWSER_URI", your TestCase must extend "%s".', PantherTestCase::class));
90
            }
91
92
            if (!$baseUri) {
93
                self::startWebServer();
94
95
                $baseUri = self::$baseUri;
96
            }
97
98
            // copied from PantherTestCaseTrait::createHttpBrowserClient()
99
            $client = new HttpBrowserClient();
100
            $urlComponents = \parse_url($baseUri);
101
            $host = $urlComponents['host'];
102
103
            if (isset($urlComponents['port'])) {
104
                $host .= ":{$urlComponents['port']}";
105
            }
106
107
            $client->setServerParameter('HTTP_HOST', $host);
108
109
            if ('https' === ($urlComponents['scheme'] ?? 'http')) {
110
                $client->setServerParameter('HTTPS', 'true');
111
            }
112
113
            /** @var HttpBrowser $browser */
114
            $browser = new $class(self::$httpBrowserClients[] = $client);
115
116
            if (!$this instanceof KernelTestCase) {
117
                return $browser;
118
            }
119
120
            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...
121
                static::bootKernel();
122
            }
123
124
            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...
125
                $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

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