Passed
Push — master ( 477db0...63a956 )
by Kevin
10:36 queued 07:22
created

ProxyTest::can_assert_not_persisted()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Zenstruck\Foundry\Tests\Functional;
4
5
use PHPUnit\Framework\AssertionFailedError;
0 ignored issues
show
Bug introduced by
The type PHPUnit\Framework\AssertionFailedError 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\Bundle\FrameworkBundle\Test\KernelTestCase;
7
use Zenstruck\Assert;
8
use Zenstruck\Foundry\AnonymousFactory;
9
use Zenstruck\Foundry\Proxy;
10
use Zenstruck\Foundry\Test\Factories;
11
use Zenstruck\Foundry\Test\ResetDatabase;
12
use Zenstruck\Foundry\Tests\Fixtures\Entity\Category;
13
use Zenstruck\Foundry\Tests\Fixtures\Entity\Contact;
14
use Zenstruck\Foundry\Tests\Fixtures\Entity\Post;
15
use Zenstruck\Foundry\Tests\Fixtures\Factories\CategoryFactory;
16
use Zenstruck\Foundry\Tests\Fixtures\Factories\PostFactory;
17
18
/**
19
 * @author Kevin Bond <[email protected]>
20
 */
21
final class ProxyTest extends KernelTestCase
22
{
23
    use Factories, ResetDatabase;
24
25
    /**
26
     * @test
27
     */
28
    public function can_assert_persisted(): void
29
    {
30
        PostFactory::createOne()->assertPersisted();
31
32
        Assert::that(function() { PostFactory::new()->withoutPersisting()->create()->assertPersisted(); })
33
            ->throws(AssertionFailedError::class, \sprintf('%s is not persisted.', Post::class))
34
        ;
35
    }
36
37
    /**
38
     * @test
39
     */
40
    public function can_assert_not_persisted(): void
41
    {
42
        PostFactory::new()->withoutPersisting()->create()->assertNotPersisted();
43
44
        Assert::that(function() { PostFactory::createOne()->assertNotPersisted(); })
45
            ->throws(AssertionFailedError::class, \sprintf('%s is persisted but it should not be.', Post::class))
46
        ;
47
    }
48
49
    /**
50
     * @test
51
     */
52
    public function can_remove_and_assert_not_persisted(): void
53
    {
54
        $post = PostFactory::createOne();
55
56
        $post->remove();
57
58
        $post->assertNotPersisted();
59
    }
60
61
    /**
62
     * @test
63
     */
64
    public function functions_are_passed_to_wrapped_object(): void
65
    {
66
        $post = PostFactory::createOne(['title' => 'my title']);
67
68
        $this->assertSame('my title', $post->getTitle());
0 ignored issues
show
Bug introduced by
The method getTitle() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

68
        $this->assertSame('my title', $post->/** @scrutinizer ignore-call */ getTitle());
Loading history...
69
    }
70
71
    /**
72
     * @test
73
     */
74
    public function can_convert_to_string_if_wrapped_object_can(): void
75
    {
76
        $post = PostFactory::createOne(['title' => 'my title']);
77
78
        $this->assertSame('my title', (string) $post);
79
    }
80
81
    /**
82
     * @test
83
     * @requires PHP >= 7.4
84
     */
85
    public function cannot_convert_to_string_if_underlying_object_cant(): void
86
    {
87
        $this->expectException(\RuntimeException::class);
88
        $this->expectExceptionMessage(\sprintf('Proxied object "%s" cannot be converted to a string.', Category::class));
89
90
        (string) CategoryFactory::createOne();
91
    }
92
93
    /**
94
     * @test
95
     * @requires PHP < 7.4
96
     */
97
    public function on_php_versions_less_than_7_4_if_underlying_object_is_missing_to_string_proxy_to_string_returns_note(): void
98
    {
99
        $this->assertSame('(no __toString)', (string) CategoryFactory::createOne());
100
    }
101
102
    /**
103
     * @test
104
     */
105
    public function can_refetch_object_if_object_manager_has_been_cleared(): void
106
    {
107
        $post = PostFactory::createOne(['title' => 'my title']);
108
109
        self::$container->get('doctrine')->getManager()->clear();
110
111
        $this->assertSame('my title', $post->refresh()->getTitle());
112
    }
113
114
    /**
115
     * @test
116
     */
117
    public function exception_thrown_if_trying_to_refresh_deleted_object(): void
118
    {
119
        $post = PostFactory::createOne();
120
121
        self::$container->get('doctrine')->getManager()->clear();
122
123
        PostFactory::repository()->truncate();
124
125
        $this->expectException(\RuntimeException::class);
126
        $this->expectExceptionMessage('The object no longer exists.');
127
128
        $post->refresh();
129
    }
130
131
    /**
132
     * @test
133
     */
134
    public function can_force_set_and_save(): void
135
    {
136
        $post = PostFactory::createOne(['title' => 'old title']);
137
138
        $post->repository()->assert()->notExists(['title' => 'new title']);
139
140
        $post->forceSet('title', 'new title')->save();
141
142
        $post->repository()->assert()->exists(['title' => 'new title']);
143
    }
144
145
    /**
146
     * @test
147
     */
148
    public function can_force_set_multiple_fields(): void
149
    {
150
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
151
152
        $this->assertSame('old title', $post->getTitle());
153
        $this->assertSame('old body', $post->getBody());
0 ignored issues
show
Bug introduced by
The method getBody() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

153
        $this->assertSame('old body', $post->/** @scrutinizer ignore-call */ getBody());
Loading history...
154
155
        $post
156
            ->forceSet('title', 'new title')
157
            ->forceSet('body', 'new body')
158
            ->save()
159
        ;
160
161
        $this->assertSame('new title', $post->getTitle());
162
        $this->assertSame('new body', $post->getBody());
163
    }
164
165
    /**
166
     * @test
167
     */
168
    public function exception_thrown_if_trying_to_autorefresh_object_with_unsaved_changes(): void
169
    {
170
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body'])
171
            ->enableAutoRefresh()
172
        ;
173
174
        $this->assertSame('old title', $post->getTitle());
175
        $this->assertSame('old body', $post->getBody());
176
177
        $post
178
            ->enableAutoRefresh()
179
            ->forceSet('title', 'new title')
180
        ;
181
182
        $this->expectException(\RuntimeException::class);
183
184
        // exception thrown because of "unsaved changes" to $post from above
185
        $post->forceSet('body', 'new body');
186
    }
187
188
    /**
189
     * @test
190
     */
191
    public function can_autorefresh_between_kernel_boots(): void
192
    {
193
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body'])
194
            ->enableAutoRefresh()
195
        ;
196
197
        $this->assertSame('old title', $post->getTitle());
198
        $this->assertSame('old body', $post->getBody());
199
200
        // reboot kernel
201
        self::ensureKernelShutdown();
202
        self::bootKernel();
203
204
        $this->assertSame('old title', $post->getTitle());
205
        $this->assertSame('old body', $post->getBody());
206
    }
207
208
    /**
209
     * @test
210
     */
211
    public function can_autorefresh_entity_with_embedded_object(): void
212
    {
213
        $contact = AnonymousFactory::new(Contact::class)->create(['name' => 'john'])
214
            ->enableAutoRefresh()
215
        ;
216
217
        $this->assertSame('john', $contact->getName());
0 ignored issues
show
Bug introduced by
The method getName() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

217
        $this->assertSame('john', $contact->/** @scrutinizer ignore-call */ getName());
Loading history...
218
219
        // I discovered when autorefreshing the second time, the embedded
220
        // object is included in the changeset when using UOW::recomputeSingleEntityChangeSet().
221
        // Changing to UOW::computeChangeSet() fixes this.
222
        $this->assertSame('john', $contact->getName());
223
        $this->assertNull($contact->getAddress()->getValue());
0 ignored issues
show
Bug introduced by
The method getAddress() does not exist on Zenstruck\Foundry\Proxy. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

223
        $this->assertNull($contact->/** @scrutinizer ignore-call */ getAddress()->getValue());
Loading history...
224
225
        $contact->getAddress()->setValue('address');
226
        $contact->save();
227
228
        $this->assertSame('address', $contact->getAddress()->getValue());
229
230
        self::ensureKernelShutdown();
231
        self::bootKernel();
232
233
        $this->assertSame('address', $contact->getAddress()->getValue());
234
    }
235
236
    /**
237
     * @test
238
     */
239
    public function force_set_all_solves_the_auto_refresh_problem(): void
240
    {
241
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
242
243
        $this->assertSame('old title', $post->getTitle());
244
        $this->assertSame('old body', $post->getBody());
245
246
        $post
247
            ->enableAutoRefresh()
248
            ->forceSetAll([
249
                'title' => 'new title',
250
                'body' => 'new body',
251
            ])
252
            ->save()
253
        ;
254
255
        $this->assertSame('new title', $post->getTitle());
256
        $this->assertSame('new body', $post->getBody());
257
    }
258
259
    /**
260
     * @test
261
     */
262
    public function without_auto_refresh_solves_the_auto_refresh_problem(): void
263
    {
264
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
265
266
        $this->assertSame('old title', $post->getTitle());
267
        $this->assertSame('old body', $post->getBody());
268
269
        $post
270
            ->enableAutoRefresh()
271
            ->withoutAutoRefresh(static function(Proxy $proxy) {
272
                $proxy
273
                    ->forceSet('title', 'new title')
274
                    ->forceSet('body', 'new body')
275
                ;
276
            })
277
            ->save()
278
        ;
279
280
        $this->assertSame('new title', $post->getTitle());
281
        $this->assertSame('new body', $post->getBody());
282
    }
283
284
    /**
285
     * @test
286
     */
287
    public function without_auto_refresh_does_not_enable_auto_refresh_if_it_was_disabled_originally(): void
288
    {
289
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
290
291
        $this->assertSame('old title', $post->getTitle());
292
        $this->assertSame('old body', $post->getBody());
293
294
        $post
295
            ->withoutAutoRefresh(static function(Proxy $proxy) {
296
                $proxy
297
                    ->forceSet('title', 'new title')
298
                    ->forceSet('body', 'new body')
299
                ;
300
            })
301
            ->forceSet('title', 'another new title')
302
            ->forceSet('body', 'another new body')
303
            ->save()
304
        ;
305
306
        $this->assertSame('another new title', $post->getTitle());
307
        $this->assertSame('another new body', $post->getBody());
308
    }
309
310
    /**
311
     * @test
312
     */
313
    public function without_auto_refresh_keeps_disabled_if_originally_disabled(): void
314
    {
315
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
316
317
        $this->assertSame('old title', $post->getTitle());
318
        $this->assertSame('old body', $post->getBody());
319
320
        $post
321
            ->withoutAutoRefresh(static function(Proxy $proxy) {
322
                $proxy
323
                    ->forceSet('title', 'new title')
324
                    ->forceSet('body', 'new body')
325
                ;
326
            })
327
            ->save()
328
            ->forceSet('title', 'another new title')
329
            ->forceSet('body', 'another new body')
330
            ->save()
331
        ;
332
333
        $this->assertSame('another new title', $post->getTitle());
334
        $this->assertSame('another new body', $post->getBody());
335
    }
336
}
337