NPlusOneQueriesTest::canAttachRoles()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 16
rs 9.9666
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace jeremykenedy\LaravelRoles\Test\Feature;
4
5
use Illuminate\Database\Events\QueryExecuted;
6
use Illuminate\Support\Facades\DB;
7
use jeremykenedy\LaravelRoles\Test\RefreshDatabase;
8
use jeremykenedy\LaravelRoles\Test\TestCase;
9
use jeremykenedy\LaravelRoles\Test\User;
10
11
class NPlusOneQueriesTest extends TestCase
12
{
13
    use RefreshDatabase;
0 ignored issues
show
introduced by
The trait jeremykenedy\LaravelRoles\Test\RefreshDatabase requires some properties which are not provided by jeremykenedy\LaravelRole...ure\NPlusOneQueriesTest: $connectionsToTransact, $dropTypes, $dropViews
Loading history...
14
15
    protected $seed = true;
16
17
    protected $usersCount = 10;
18
    /**
19
     * @var int in case UsersTableSeeder seeds your users,
20
     *          please indicate their number here
21
     */
22
    protected $usersCountCorrection = 0;
23
    protected $rolesCount = 3; //correct according to your data
24
    protected $permissionsCount = 4; //correct according to your data
25
26
    protected $queries = 0;
27
28
    protected function setUp(): void
29
    {
30
        parent::setUp();
31
32
        $this->assertEquals($this->rolesCount, config('roles.models.role')::count());
33
        $this->assertEquals($this->permissionsCount, config('roles.models.permission')::count());
34
35
        DB::listen(function (QueryExecuted $query) {
0 ignored issues
show
Unused Code introduced by
The parameter $query is not used and could be removed. ( Ignorable by Annotation )

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

35
        DB::listen(function (/** @scrutinizer ignore-unused */ QueryExecuted $query) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
36
            $this->queries++;
37
        });
38
    }
39
40
    /** @test */
41
    public function canPreloadRolesOnCollection(): void
42
    {
43
        $roleIds = config('roles.models.role')::pluck('id');
44
45
        User::factory($this->usersCount)->create()
46
            ->each(function (User $user) use ($roleIds) {
47
                $user->roles()->attach($roleIds);
48
            });
49
        $this->assertEquals($this->usersCount, User::count() - $this->usersCountCorrection);
50
51
        $this->queries = 0;
52
53
        // without eager load
54
        $users = User::get();
55
        $this->assertQueries(1);
56
57
        $users->each(function (User $user) {
58
            $user->getRoles();
59
        });
60
        $this->queries = $this->queries - $this->usersCountCorrection;
61
        $this->assertQueries($this->usersCount);
62
63
        // with eager load
64
        $users = User::with('roles')->get();
65
        $this->assertQueries(2);
66
67
        $users->each(function (User $user) {
68
            $user->getRoles();
69
        });
70
        $this->assertQueries(0);
71
    }
72
73
    /** @test */
74
    public function canAttachRoles()
75
    {
76
        /** @var User $user */
77
        $user = User::factory()->create();
78
        $roleId = config('roles.models.role')::value('id');
79
80
        $this->queries = 0;
81
        $user->attachRole($roleId);
82
        // getRoles + attach
83
        $this->assertQueries(2);
84
85
        $this->queries = 0;
86
        $user->detachAllRoles();
87
        $user->attachRole($roleId);
88
        // detach + getRoles + attach
89
        $this->assertQueries(3);
90
    }
91
92
    /** @test */
93
    public function itCachesRoles()
94
    {
95
        /** @var User $user */
96
        $user = User::factory()->create();
97
98
        $this->queries = 0;
99
        $user->getRoles();
100
        $this->assertQueries(1);
101
102
        $user->getRoles();
103
        $this->assertQueries(0);
104
105
        $user->roles;
0 ignored issues
show
Bug Best Practice introduced by
The property $roles is declared protected in jeremykenedy\LaravelRoles\Test\User. Since you implement __get, consider adding a @property or @property-read.
Loading history...
106
        $this->assertQueries(0);
107
    }
108
109
    /** @test */
110
    public function itCachesPermissions()
111
    {
112
        /** @var User $user */
113
        $user = User::factory()->create();
114
        $roleIds = config('roles.models.role')::pluck('id');
115
        $user->roles()->attach($roleIds);
116
117
        $this->queries = 0;
118
        $user->getPermissions();
119
        // rolePermissions(+getRoles) + userPermissions
120
        $this->assertQueries(3);
121
122
        $user->getPermissions();
123
        $this->assertQueries(0);
124
125
        $user->permissions;
0 ignored issues
show
Bug Best Practice introduced by
The property $permissions is declared protected in jeremykenedy\LaravelRoles\Test\User. Since you implement __get, consider adding a @property or @property-read.
Loading history...
126
        $this->assertQueries(0);
127
128
        /** @var User $user */
129
        $user = User::find($user->id);
130
131
        $this->queries = 0;
132
        $user->getRoles();
133
        $this->assertQueries(1);
134
        $user->getPermissions();
135
        // rolePermissions + userPermissions
136
        $this->assertQueries(2);
137
    }
138
139
    /** @test */
140
    public function canPreloadPermissionsOnCollection(): void
141
    {
142
        $roleIds = config('roles.models.role')::pluck('id');
143
144
        User::factory($this->usersCount)->create()
145
            ->each(function (User $user) use ($roleIds) {
146
                $user->roles()->attach($roleIds);
147
            });
148
        $this->assertEquals($this->usersCount, User::count() - $this->usersCountCorrection);
149
150
        $this->queries = 0;
151
152
        // without eager load
153
        $users = User::get();
154
        $this->assertQueries(1);
155
156
        $users->each(function (User $user) {
157
            $user->getPermissions();
158
        });
159
        // rolePermissions(+getRoles) + userPermissions
160
        $this->assertQueries(($this->usersCount + $this->usersCountCorrection) * 3);
161
162
        // with eager load
163
        // TODO: 'rolePermissions' relation
164
        $users = User::with('roles', 'userPermissions')->get();
165
        $this->assertQueries(3);
166
167
        $users->each(function (User $user) {
168
            $user->getPermissions();
169
        });
170
        // TODO: optimize via relations: userPermissions and rolePermissions
171
        $this->assertQueries(20 + $this->usersCountCorrection * 2);
172
        // $this->assertQueries(0);
173
    }
174
175
    protected function assertQueries(int $count): void
176
    {
177
        $this->assertEquals($count, $this->queries);
178
        $this->queries = 0;
179
    }
180
}
181