Passed
Pull Request — master (#131)
by Kevin
02:32
created

ProxyTest::can_autorefresh_between_kernel_boots()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 15
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Zenstruck\Foundry\Tests\Functional;
4
5
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
6
use Zenstruck\Foundry\Factory;
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
        $post = (new Factory(Contact::class))->create(['name' => 'john'])
197
            ->enableAutoRefresh()
198
        ;
199
200
        $this->assertSame('john', $post->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', $post->/** @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', $post->getName());
206
    }
207
208
    /**
209
     * @test
210
     */
211
    public function force_set_all_solves_the_auto_refresh_problem(): void
212
    {
213
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
214
215
        $this->assertSame('old title', $post->getTitle());
216
        $this->assertSame('old body', $post->getBody());
217
218
        $post
219
            ->enableAutoRefresh()
220
            ->forceSetAll([
221
                'title' => 'new title',
222
                'body' => 'new body',
223
            ])
224
            ->save()
225
        ;
226
227
        $this->assertSame('new title', $post->getTitle());
228
        $this->assertSame('new body', $post->getBody());
229
    }
230
231
    /**
232
     * @test
233
     */
234
    public function without_auto_refresh_solves_the_auto_refresh_problem(): void
235
    {
236
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
237
238
        $this->assertSame('old title', $post->getTitle());
239
        $this->assertSame('old body', $post->getBody());
240
241
        $post
242
            ->enableAutoRefresh()
243
            ->withoutAutoRefresh(static function(Proxy $proxy) {
244
                $proxy
245
                    ->forceSet('title', 'new title')
246
                    ->forceSet('body', 'new body')
247
                ;
248
            })
249
            ->save()
250
        ;
251
252
        $this->assertSame('new title', $post->getTitle());
253
        $this->assertSame('new body', $post->getBody());
254
    }
255
256
    /**
257
     * @test
258
     */
259
    public function without_auto_refresh_does_not_enable_auto_refresh_if_it_was_disabled_originally(): void
260
    {
261
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
262
263
        $this->assertSame('old title', $post->getTitle());
264
        $this->assertSame('old body', $post->getBody());
265
266
        $post
267
            ->withoutAutoRefresh(static function(Proxy $proxy) {
268
                $proxy
269
                    ->forceSet('title', 'new title')
270
                    ->forceSet('body', 'new body')
271
                ;
272
            })
273
            ->forceSet('title', 'another new title')
274
            ->forceSet('body', 'another new body')
275
            ->save()
276
        ;
277
278
        $this->assertSame('another new title', $post->getTitle());
279
        $this->assertSame('another new body', $post->getBody());
280
    }
281
282
    /**
283
     * @test
284
     */
285
    public function without_auto_refresh_keeps_disabled_if_originally_disabled(): void
286
    {
287
        $post = PostFactory::createOne(['title' => 'old title', 'body' => 'old body']);
288
289
        $this->assertSame('old title', $post->getTitle());
290
        $this->assertSame('old body', $post->getBody());
291
292
        $post
293
            ->withoutAutoRefresh(static function(Proxy $proxy) {
294
                $proxy
295
                    ->forceSet('title', 'new title')
296
                    ->forceSet('body', 'new body')
297
                ;
298
            })
299
            ->save()
300
            ->forceSet('title', 'another new title')
301
            ->forceSet('body', 'another new body')
302
            ->save()
303
        ;
304
305
        $this->assertSame('another new title', $post->getTitle());
306
        $this->assertSame('another new body', $post->getBody());
307
    }
308
}
309