Passed
Push — master ( 0872be...82502b )
by Kevin
06:23 queued 03:16
created

ProxyTest::can_force_set_and_save()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 4
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 9
rs 10
1
<?php
2
3
namespace Zenstruck\Foundry\Tests\Functional;
4
5
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
6
use Zenstruck\Foundry\AnonymousFactory;
7
use Zenstruck\Foundry\Proxy;
8
use Zenstruck\Foundry\Test\Factories;
9
use Zenstruck\Foundry\Test\ResetDatabase;
10
use Zenstruck\Foundry\Tests\Fixtures\Entity\Category;
11
use Zenstruck\Foundry\Tests\Fixtures\Entity\Contact;
12
use Zenstruck\Foundry\Tests\Fixtures\Factories\CategoryFactory;
13
use Zenstruck\Foundry\Tests\Fixtures\Factories\PostFactory;
14
15
/**
16
 * @author Kevin Bond <[email protected]>
17
 */
18
final class ProxyTest extends KernelTestCase
19
{
20
    use Factories, ResetDatabase;
21
22
    /**
23
     * @test
24
     */
25
    public function can_assert_persisted(): void
26
    {
27
        $post = PostFactory::createOne();
28
29
        $post->assertPersisted();
30
    }
31
32
    /**
33
     * @test
34
     */
35
    public function can_remove_and_assert_not_persisted(): void
36
    {
37
        $post = PostFactory::createOne();
38
39
        $post->remove();
40
41
        $post->assertNotPersisted();
42
    }
43
44
    /**
45
     * @test
46
     */
47
    public function functions_are_passed_to_wrapped_object(): void
48
    {
49
        $post = PostFactory::createOne(['title' => 'my title']);
50
51
        $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

51
        $this->assertSame('my title', $post->/** @scrutinizer ignore-call */ getTitle());
Loading history...
52
    }
53
54
    /**
55
     * @test
56
     */
57
    public function can_convert_to_string_if_wrapped_object_can(): void
58
    {
59
        $post = PostFactory::createOne(['title' => 'my title']);
60
61
        $this->assertSame('my title', (string) $post);
62
    }
63
64
    /**
65
     * @test
66
     * @requires PHP >= 7.4
67
     */
68
    public function cannot_convert_to_string_if_underlying_object_cant(): void
69
    {
70
        $this->expectException(\RuntimeException::class);
71
        $this->expectExceptionMessage(\sprintf('Proxied object "%s" cannot be converted to a string.', Category::class));
72
73
        (string) CategoryFactory::createOne();
74
    }
75
76
    /**
77
     * @test
78
     * @requires PHP < 7.4
79
     */
80
    public function on_php_versions_less_than_7_4_if_underlying_object_is_missing_to_string_proxy_to_string_returns_note(): void
81
    {
82
        $this->assertSame('(no __toString)', (string) CategoryFactory::createOne());
83
    }
84
85
    /**
86
     * @test
87
     */
88
    public function can_refetch_object_if_object_manager_has_been_cleared(): void
89
    {
90
        $post = PostFactory::createOne(['title' => 'my title']);
91
92
        self::$container->get('doctrine')->getManager()->clear();
93
94
        $this->assertSame('my title', $post->refresh()->getTitle());
95
    }
96
97
    /**
98
     * @test
99
     */
100
    public function exception_thrown_if_trying_to_refresh_deleted_object(): void
101
    {
102
        $post = PostFactory::createOne();
103
104
        self::$container->get('doctrine')->getManager()->clear();
105
106
        PostFactory::repository()->truncate();
107
108
        $this->expectException(\RuntimeException::class);
109
        $this->expectExceptionMessage('The object no longer exists.');
110
111
        $post->refresh();
112
    }
113
114
    /**
115
     * @test
116
     */
117
    public function can_force_set_and_save(): void
118
    {
119
        $post = PostFactory::createOne(['title' => 'old title']);
120
121
        $post->repository()->assert()->notExists(['title' => 'new title']);
122
123
        $post->forceSet('title', 'new title')->save();
124
125
        $post->repository()->assert()->exists(['title' => 'new title']);
126
    }
127
128
    /**
129
     * @test
130
     */
131
    public function can_force_set_multiple_fields(): void
132
    {
133
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
134
135
        $this->assertSame('old title', $post->getTitle());
136
        $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

136
        $this->assertSame('old body', $post->/** @scrutinizer ignore-call */ getBody());
Loading history...
137
138
        $post
139
            ->forceSet('title', 'new title')
140
            ->forceSet('body', 'new body')
141
            ->save()
142
        ;
143
144
        $this->assertSame('new title', $post->getTitle());
145
        $this->assertSame('new body', $post->getBody());
146
    }
147
148
    /**
149
     * @test
150
     */
151
    public function exception_thrown_if_trying_to_autorefresh_object_with_unsaved_changes(): void
152
    {
153
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body'])
154
            ->enableAutoRefresh()
155
        ;
156
157
        $this->assertSame('old title', $post->getTitle());
158
        $this->assertSame('old body', $post->getBody());
159
160
        $post
161
            ->enableAutoRefresh()
162
            ->forceSet('title', 'new title')
163
        ;
164
165
        $this->expectException(\RuntimeException::class);
166
167
        // exception thrown because of "unsaved changes" to $post from above
168
        $post->forceSet('body', 'new body');
169
    }
170
171
    /**
172
     * @test
173
     */
174
    public function can_autorefresh_between_kernel_boots(): void
175
    {
176
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body'])
177
            ->enableAutoRefresh()
178
        ;
179
180
        $this->assertSame('old title', $post->getTitle());
181
        $this->assertSame('old body', $post->getBody());
182
183
        // reboot kernel
184
        self::ensureKernelShutdown();
185
        self::bootKernel();
186
187
        $this->assertSame('old title', $post->getTitle());
188
        $this->assertSame('old body', $post->getBody());
189
    }
190
191
    /**
192
     * @test
193
     */
194
    public function can_autorefresh_entity_with_embedded_object(): void
195
    {
196
        $contact = AnonymousFactory::new(Contact::class)->create(['name' => 'john'])
197
            ->enableAutoRefresh()
198
        ;
199
200
        $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

200
        $this->assertSame('john', $contact->/** @scrutinizer ignore-call */ getName());
Loading history...
201
202
        // I discovered when autorefreshing the second time, the embedded
203
        // object is included in the changeset when using UOW::recomputeSingleEntityChangeSet().
204
        // Changing to UOW::computeChangeSet() fixes this.
205
        $this->assertSame('john', $contact->getName());
206
        $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

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