Passed
Push — 1.x ( 25b111...22285f )
by Kevin
06:44
created

PantherBrowser::follow()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 4
nop 1
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Zenstruck\Browser;
4
5
use PHPUnit\Framework\Assert as PHPUnit;
0 ignored issues
show
Bug introduced by
The type PHPUnit\Framework\Assert was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Symfony\Component\Filesystem\Filesystem;
7
use Symfony\Component\Panther\Client;
8
use Symfony\Component\VarDumper\VarDumper;
9
use Zenstruck\Browser;
10
use Zenstruck\Browser\Extension\Html;
11
use Zenstruck\Browser\Mink\PantherDriver;
12
use Zenstruck\Browser\Response\PantherResponse;
13
14
/**
15
 * @author Kevin Bond <[email protected]>
16
 *
17
 * @experimental in 1.0
18
 */
19
class PantherBrowser extends Browser
20
{
21
    use Html;
22
23
    private Client $client;
24
    private ?string $screenshotDir = null;
25
    private ?string $consoleLogDir = null;
26
    private array $savedScreenshots = [];
27
    private array $savedConsoleLogs = [];
28
29
    final public function __construct(Client $client)
30
    {
31
        parent::__construct(new PantherDriver($this->client = $client));
32
    }
33
34
    final public function client(): Client
35
    {
36
        return $this->client;
37
    }
38
39
    final public function setScreenshotDir(string $dir): self
40
    {
41
        $this->screenshotDir = $dir;
42
43
        return $this;
44
    }
45
46
    final public function setConsoleLogDir(string $dir): self
47
    {
48
        $this->consoleLogDir = $dir;
49
50
        return $this;
51
    }
52
53
    /**
54
     * @return static
55
     */
56
    public function follow(string $link): self
57
    {
58
        if (!$element = $this->documentElement()->findLink($link)) {
59
            PHPUnit::fail(\sprintf('Link "%s" not found.', $link));
60
        }
61
62
        if (!$element->isVisible()) {
63
            PHPUnit::fail(\sprintf('Link "%s" is not visible.', $link));
64
        }
65
66
        $this->documentElement()->clickLink($link);
67
68
        return $this;
69
    }
70
71
    /**
72
     * @return static
73
     */
74
    final public function assertVisible(string $selector): self
75
    {
76
        return $this->wrapMinkExpectation(function() use ($selector) {
77
            $element = $this->webAssert()->elementExists('css', $selector);
78
79
            PHPUnit::assertTrue($element->isVisible());
80
        });
81
    }
82
83
    /**
84
     * @return static
85
     */
86
    final public function assertNotVisible(string $selector): self
87
    {
88
        $element = $this->documentElement()->find('css', $selector);
89
90
        if (!$element) {
91
            PHPUnit::assertTrue(true);
92
93
            return $this;
94
        }
95
96
        PHPUnit::assertFalse($element->isVisible());
97
98
        return $this;
99
    }
100
101
    /**
102
     * @return static
103
     */
104
    final public function wait(int $milliseconds): self
105
    {
106
        \usleep($milliseconds * 1000);
107
108
        return $this;
109
    }
110
111
    /**
112
     * @return static
113
     */
114
    final public function waitUntilVisible(string $selector): self
115
    {
116
        $this->client->waitForVisibility($selector);
117
118
        return $this;
119
    }
120
121
    /**
122
     * @return static
123
     */
124
    final public function waitUntilNotVisible(string $selector): self
125
    {
126
        $this->client->waitForInvisibility($selector);
127
128
        return $this;
129
    }
130
131
    /**
132
     * @return static
133
     */
134
    final public function waitUntilSeeIn(string $selector, string $expected): self
135
    {
136
        $this->client->waitForElementToContain($selector, $expected);
137
138
        return $this;
139
    }
140
141
    /**
142
     * @return static
143
     */
144
    final public function waitUntilNotSeeIn(string $selector, string $expected): self
145
    {
146
        $this->client->waitForElementToNotContain($selector, $expected);
147
148
        return $this;
149
    }
150
151
    /**
152
     * @return static
153
     */
154
    final public function inspect(): self
155
    {
156
        if (!($_SERVER['PANTHER_NO_HEADLESS'] ?? false)) {
157
            throw new \RuntimeException('The "PANTHER_NO_HEADLESS" env variable must be set to inspect.');
158
        }
159
160
        \fwrite(STDIN, "\n\nInspecting the browser.\n\nPress enter to continue...");
161
        \fgets(STDIN);
162
163
        return $this;
164
    }
165
166
    /**
167
     * @return static
168
     */
169
    final public function takeScreenshot(string $filename): self
170
    {
171
        if ($this->screenshotDir) {
172
            $filename = \sprintf('%s/%s', \rtrim($this->screenshotDir, '/'), \ltrim($filename, '/'));
173
        }
174
175
        $this->client->takeScreenshot($this->savedScreenshots[] = $filename);
176
177
        return $this;
178
    }
179
180
    final public function saveConsoleLog(string $filename): self
181
    {
182
        if ($this->consoleLogDir) {
183
            $filename = \sprintf('%s/%s', \rtrim($this->consoleLogDir, '/'), \ltrim($filename, '/'));
184
        }
185
186
        $log = $this->client->manage()->getLog('browser');
187
        $log = \json_encode($log, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
188
189
        (new Filesystem())->dumpFile($this->savedConsoleLogs[] = $filename, $log);
190
191
        return $this;
192
    }
193
194
    final public function dumpConsoleLog(): self
195
    {
196
        VarDumper::dump($this->client->manage()->getLog('browser'));
197
198
        return $this;
199
    }
200
201
    final public function ddConsoleLog(): void
202
    {
203
        $this->dumpConsoleLog();
204
        $this->die();
205
    }
206
207
    final public function ddScreenshot(string $filename = 'screenshot.png'): void
208
    {
209
        $this->takeScreenshot($filename);
210
211
        echo \sprintf("\n\nScreenshot saved as \"%s\".\n\n", \end($this->savedScreenshots));
212
213
        $this->die();
214
    }
215
216
    /**
217
     * @internal
218
     */
219
    final public function dumpCurrentState(string $filename): void
220
    {
221
        parent::dumpCurrentState($filename);
222
223
        $this->takeScreenshot("{$filename}.png");
224
        $this->saveConsoleLog("{$filename}.log");
225
    }
226
227
    /**
228
     * @internal
229
     */
230
    public function savedArtifacts(): array
231
    {
232
        return \array_merge(
233
            parent::savedArtifacts(),
234
            ['Saved Console Logs' => $this->savedConsoleLogs, 'Saved Screenshots' => $this->savedScreenshots]
235
        );
236
    }
237
238
    protected function response(): PantherResponse
239
    {
240
        return new PantherResponse($this->minkSession());
241
    }
242
243
    protected function die(): void
244
    {
245
        $this->client->quit();
246
        parent::die();
247
    }
248
}
249