Passed
Push — 1.x ( 13d0d8...e7706b )
by Kevin
01:47
created

Browser::savedArtifacts()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Zenstruck;
4
5
use Behat\Mink\Driver\DriverInterface;
6
use Behat\Mink\Element\DocumentElement;
7
use Behat\Mink\Exception\ExpectationException;
8
use Behat\Mink\Mink;
9
use Behat\Mink\Session;
10
use Behat\Mink\WebAssert;
11
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...
12
use Symfony\Component\Filesystem\Filesystem;
13
use Symfony\Component\VarDumper\VarDumper;
14
use Zenstruck\Browser\Component;
15
use Zenstruck\Browser\Response;
16
use Zenstruck\Browser\Test\Constraint\UrlMatches;
17
use Zenstruck\Browser\Util\FunctionExecutor;
18
19
/**
20
 * @author Kevin Bond <[email protected]>
21
 */
22
class Browser
23
{
24
    private const SESSION = 'app';
25
26
    private Mink $mink;
27
    private ?string $sourceDir = null;
28
    private array $savedSources = [];
29
30
    public function __construct(DriverInterface $driver)
31
    {
32
        $this->mink = new Mink([self::SESSION => new Session($driver)]);
33
    }
34
35
    /**
36
     * @return static
37
     */
38
    public static function create(callable $factory): self
39
    {
40
        $browser = $factory();
41
42
        if (!$browser instanceof self) {
43
            throw new \RuntimeException(\sprintf('The factory callable must return an instance of "%s".', self::class));
44
        }
45
46
        return $browser;
47
    }
48
49
    /**
50
     * @return static
51
     */
52
    final public function setSourceDir(string $dir): self
53
    {
54
        $this->sourceDir = $dir;
55
56
        return $this;
57
    }
58
59
    final public function minkSession(): Session
60
    {
61
        return $this->mink->getSession(self::SESSION);
62
    }
63
64
    final public function webAssert(): WebAssert
65
    {
66
        return $this->mink->assertSession(self::SESSION);
67
    }
68
69
    final public function documentElement(): DocumentElement
70
    {
71
        return $this->minkSession()->getPage();
72
    }
73
74
    /**
75
     * @return static
76
     */
77
    final public function visit(string $uri): self
78
    {
79
        $this->minkSession()->visit($uri);
80
81
        return $this;
82
    }
83
84
    /**
85
     * @param array $parts The url parts to check (@see parse_url)
86
     *
87
     * @return static
88
     */
89
    final public function assertOn(string $expected, array $parts = ['path', 'query', 'fragment']): self
90
    {
91
        PHPUnit::assertThat($expected, new UrlMatches($this->minkSession()->getCurrentUrl(), $parts));
92
93
        return $this;
94
    }
95
96
    /**
97
     * @param array $parts The url parts to check (@see parse_url)
98
     *
99
     * @return static
100
     */
101
    final public function assertNotOn(string $expected, array $parts = ['path', 'query', 'fragment']): self
102
    {
103
        PHPUnit::assertThat(
104
            $expected,
105
            PHPUnit::logicalNot(new UrlMatches($this->minkSession()->getCurrentUrl(), $parts))
106
        );
107
108
        return $this;
109
    }
110
111
    /**
112
     * @return static
113
     */
114
    final public function assertContains(string $expected): self
115
    {
116
        return $this->wrapMinkExpectation(
117
            fn() => $this->webAssert()->responseContains($expected)
118
        );
119
    }
120
121
    /**
122
     * @return static
123
     */
124
    final public function assertNotContains(string $expected): self
125
    {
126
        return $this->wrapMinkExpectation(
127
            fn() => $this->webAssert()->responseNotContains($expected)
128
        );
129
    }
130
131
    /**
132
     * @return static
133
     */
134
    final public function use(callable $callback): self
135
    {
136
        FunctionExecutor::createFor($callback)
137
            ->replaceUntypedArgument($this)
138
            ->replaceTypedArgument(self::class, $this)
139
            ->replaceTypedArgument(Component::class, fn(string $class) => new $class($this))
140
            ->execute()
141
        ;
142
143
        return $this;
144
    }
145
146
    /**
147
     * @return static
148
     */
149
    final public function saveSource(string $filename): self
150
    {
151
        if ($this->sourceDir) {
152
            $filename = \sprintf('%s/%s', \rtrim($this->sourceDir, '/'), \ltrim($filename, '/'));
153
        }
154
155
        (new Filesystem())->dumpFile($this->savedSources[] = $filename, $this->response()->raw());
156
157
        return $this;
158
    }
159
160
    /**
161
     * @return static
162
     */
163
    final public function dump(?string $selector = null): self
164
    {
165
        VarDumper::dump($selector ? $this->response()->find($selector) : $this->response()->raw());
166
167
        return $this;
168
    }
169
170
    final public function dd(?string $selector = null): void
171
    {
172
        $this->dump($selector);
173
        $this->die();
174
    }
175
176
    /**
177
     * @internal
178
     */
179
    public function dumpCurrentState(string $filename): void
180
    {
181
        $this->saveSource("{$filename}.txt");
182
    }
183
184
    /**
185
     * @internal
186
     */
187
    public function savedArtifacts(): array
188
    {
189
        return ['Saved Source Files' => $this->savedSources];
190
    }
191
192
    protected function response(): Response
193
    {
194
        return Response::createFor($this->minkSession());
195
    }
196
197
    /**
198
     * @return static
199
     */
200
    final protected function wrapMinkExpectation(callable $callback): self
201
    {
202
        try {
203
            $callback();
204
            PHPUnit::assertTrue(true);
205
        } catch (ExpectationException $e) {
206
            PHPUnit::fail($e->getMessage());
207
        }
208
209
        return $this;
210
    }
211
212
    protected function die(): void
213
    {
214
        exit(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
215
    }
216
}
217