Completed
Pull Request — master (#4165)
by Craig
17:20
created

UserCreationApiTest::testCreateUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 20
c 1
b 1
f 0
nc 1
nop 0
dl 0
loc 27
rs 9.6
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula Foundation - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\ZAuthModule\Tests\Api;
15
16
use Doctrine\Persistence\ManagerRegistry;
17
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
18
use Symfony\Component\Dotenv\Dotenv;
19
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
20
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
21
use Symfony\Component\Validator\ConstraintViolationList;
22
use Symfony\Component\Validator\Validation;
23
use Zikula\ExtensionsModule\Api\ApiInterface\VariableApiInterface;
24
use Zikula\GroupsModule\Constant as GroupsConstant;
25
use Zikula\GroupsModule\Entity\GroupEntity;
26
use Zikula\GroupsModule\Entity\RepositoryInterface\GroupRepositoryInterface;
27
use Zikula\UsersModule\Api\ApiInterface\CurrentUserApiInterface;
28
use Zikula\UsersModule\Constant as UsersConstant;
29
use Zikula\UsersModule\Entity\UserEntity;
30
use Zikula\ZAuthModule\Api\ApiInterface\UserCreationApiInterface;
31
use Zikula\ZAuthModule\Api\UserCreationApi;
32
use Zikula\ZAuthModule\Entity\AuthenticationMappingEntity;
33
use Zikula\ZAuthModule\ZAuthConstant;
34
35
class UserCreationApiTest extends KernelTestCase
36
{
37
    /**
38
     * @var UserCreationApiInterface
39
     */
40
    private $api;
41
42
    protected function setUp(): void
43
    {
44
        // load test env vars
45
        $dotenv = new Dotenv();
46
        $dotenv->load('.env.test');
47
48
        self::bootKernel();
49
        $container = self::$container;
50
        $validator = $container->get('validator');
51
52
        $currentUserApi = $this->createMock(CurrentUserApiInterface::class);
53
        $currentUserApi->method('get')->willReturn(UsersConstant::USER_ID_ADMIN);
54
        $encoder = $this->createPasswordEncoder();
55
        $encoderFactory = $this->createEncoderFactory($encoder);
56
        $managerRegistry = $this->createMock(ManagerRegistry::class);
57
        $variableApi = $this->createMock(VariableApiInterface::class);
58
        $variableApi->method('get')->willReturn(ZAuthConstant::DEFAULT_EMAIL_VERIFICATION_REQUIRED);
59
        $groupRepository = $this->createMock(GroupRepositoryInterface::class);
60
        $groupRepository->method('findAllAndIndexBy')->willReturn($this->createGroups());
61
        $this->api = new UserCreationApi(
62
            $validator,
0 ignored issues
show
Bug introduced by
It seems like $validator can also be of type null; however, parameter $validator of Zikula\ZAuthModule\Api\U...ationApi::__construct() does only seem to accept Symfony\Component\Valida...ator\ValidatorInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

62
            /** @scrutinizer ignore-type */ $validator,
Loading history...
63
            $currentUserApi,
64
            $encoderFactory,
65
            $managerRegistry,
66
            $variableApi,
67
            $groupRepository
68
        );
69
    }
70
71
    /**
72
     * @dataProvider isValidUserDataProvider
73
     */
74
    public function testIsValidUserData($expected, array $user): void
75
    {
76
        $this->assertEquals($expected, $this->api->isValidUserData($user));
77
    }
78
79
    public function testIsValidUserDataArray(): void
80
    {
81
        $users = $this->getValidUsersArray();
82
        $errors = $this->api->isValidUserDataArray($users);
83
        $this->assertTrue($errors);
84
85
        $users = $this->getInvalidUsersArray();
86
        $errors = $this->api->isValidUserDataArray($users);
87
        $this->assertNotTrue($errors);
88
        $this->assertInstanceOf(ConstraintViolationList::class, $errors);
89
        $this->assertEquals(4, $errors->count());
90
        $this->assertEquals('This value is not a valid email address.', $errors[0]->getMessage());
91
        $this->assertEquals('This value is too short. It should have 5 characters or more.', $errors[1]->getMessage());
92
        $this->assertEquals('The value you selected is not a valid choice.', $errors[2]->getMessage());
93
        $this->assertEquals('This value is not valid.', $errors[3]->getMessage());
94
    }
95
96
    public function testCreateUser(): void
97
    {
98
        $this->api->createUser([
99
            'uname' => 'foo',
100
            'email' => '[email protected]',
101
            'pass' => '12345678'
102
        ]);
103
104
        $users = $this->api->getCreatedUsers();
105
        $hash = array_key_first($users);
106
        /** @var UserEntity $newUser */
107
        $newUser = $users[$hash];
108
        $this->assertEquals('foo', $newUser->getUname());
109
        $this->assertEquals('[email protected]', $newUser->getEmail());
110
        $this->assertEquals(1, $newUser->getActivated());
111
        $this->assertEquals(1, $newUser->getGroups()->count());
112
        $this->assertEquals(null, $newUser->getUid());
113
114
        $mappings = $this->api->getCreatedMappings();
115
        $this->assertArrayHasKey($hash, $mappings);
116
        /** @var AuthenticationMappingEntity $newMapping */
117
        $newMapping = $mappings[$hash];
118
        $this->assertEquals('foo', $newMapping->getUname());
119
        $this->assertEquals('[email protected]', $newMapping->getEmail());
120
        $this->assertEquals('thisIsAnEncodedPassword!', $newMapping->getPass());
121
        $this->assertEquals(ZAuthConstant::AUTHENTICATION_METHOD_EITHER, $newMapping->getMethod());
122
        $this->assertNotEquals(ZAuthConstant::DEFAULT_EMAIL_VERIFICATION_REQUIRED, $newMapping->isVerifiedEmail());
123
    }
124
125
    public function testCreateUsers(): void
126
    {
127
        $users = $this->getValidUsersArray();
128
        $errors = $this->api->createUsers($users);
129
        $this->assertCount(0, $errors);
130
        $this->assertCount(10, $this->api->getCreatedUsers());
131
        $this->assertCount(10, $this->api->getCreatedMappings());
132
133
        $this->api->clearCreated();
134
        $users = $this->getInvalidUsersArray();
135
        $errors = $this->api->createUsers($users);
136
        $this->assertCount(4, $errors);
137
        $this->assertCount(6, $this->api->getCreatedUsers());
138
        $this->assertCount(6, $this->api->getCreatedMappings());
139
        $this->assertEquals('Row 0 with email `foo0@bar` and uname `foo0` is invalid and was rejected.', $errors[0]);
140
        $this->assertEquals('Row 2 with email `[email protected]` and uname `foo2` is invalid and was rejected.', $errors[1]);
141
        $this->assertEquals('Row 3 with email `[email protected]` and uname `foo3` is invalid and was rejected.', $errors[2]);
142
        $this->assertEquals('Row 9 with email `[email protected]` and uname `foo9` is invalid and was rejected.', $errors[3]);
143
    }
144
145
    public function isValidUserDataProvider()
146
    {
147
        return [
148
            ['This field is missing.', []],
149
            ['This field is missing.', ['uname' => 'foo', 'pass' => '12345678']],
150
            ['This field is missing.', ['uname' => 'foo', 'pass' => '12345678', 'bar' => 'foo']],
151
            ['This field is missing.', ['uname' => 'foo', 'email' => '[email protected]']],
152
            ['This value is not a valid email address.', ['uname' => 'foo', 'pass' => '12345678', 'email' => 'foo']],
153
            ['This value should not be blank.', ['uname' => '', 'pass' => '12345678', 'email' => '[email protected]']],
154
            ['This value is too short. It should have 5 characters or more.', ['uname' => 'foo', 'pass' => '123', 'email' => '[email protected]']],
155
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]']],
156
157
            ['The value you selected is not a valid choice.', ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 2]],
158
            ['The value you selected is not a valid choice.', ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => '2']],
159
            ['This value should be of type numeric.', ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 'foo']],
160
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => '1']],
161
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 0]],
162
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 1]],
163
            ['The value you selected is not a valid choice.', ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => 2]],
164
            ['The value you selected is not a valid choice.', ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => '2']],
165
            ['This value should be of type numeric.', ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => 'foo']],
166
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => '1']],
167
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => 0]],
168
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => 1]],
169
            ['This value should be of type string.', ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'groups' => 1]],
170
            ['This value is not valid.', ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'groups' => 'users']],
171
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'groups' => '1']],
172
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'groups' => '1|2|3']],
173
174
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => '1', 'sendmail' => '1', 'groups' => '1']],
175
            [true, ['uname' => 'foo', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 1, 'sendmail' => 1, 'groups' => '1|2|12345']],
176
        ];
177
    }
178
179
    private function getValidUsersArray(): array
180
    {
181
        return [
182
            ['uname' => 'foo0', 'pass' => '12345678', 'email' => '[email protected]'],
183
            ['uname' => 'foo1', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => '1'],
184
            ['uname' => 'foo2', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 0],
185
            ['uname' => 'foo3', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 1],
186
            ['uname' => 'foo4', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => '1'],
187
            ['uname' => 'foo5', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => 1],
188
            ['uname' => 'foo6', 'pass' => '12345678', 'email' => '[email protected]', 'groups' => '1|57'],
189
            ['uname' => 'foo7', 'pass' => '12345678', 'email' => '[email protected]', 'groups' => '1|2'],
190
            ['uname' => 'foo8', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => '1', 'sendmail' => '1', 'groups' => '1'],
191
            ['uname' => 'foo9', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 1, 'sendmail' => 1, 'groups' => '1|2|3'],
192
        ];
193
    }
194
195
    private function getInvalidUsersArray(): array
196
    {
197
        return [
198
            ['uname' => 'foo0', 'pass' => '12345678', 'email' => 'foo0@bar'], // invalid
199
            ['uname' => 'foo1', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => '1'],
200
            ['uname' => 'foo2', 'pass' => '123', 'email' => '[email protected]', 'activated' => 0], // invalid
201
            ['uname' => 'foo3', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 9], // invalid
202
            ['uname' => 'foo4', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => '1'],
203
            ['uname' => 'foo5', 'pass' => '12345678', 'email' => '[email protected]', 'sendmail' => 1],
204
            ['uname' => 'foo6', 'pass' => '12345678', 'email' => '[email protected]', 'groups' => '1|57'],
205
            ['uname' => 'foo7', 'pass' => '12345678', 'email' => '[email protected]', 'groups' => '1|2'],
206
            ['uname' => 'foo8', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => '1', 'sendmail' => '1', 'groups' => '1'],
207
            ['uname' => 'foo9', 'pass' => '12345678', 'email' => '[email protected]', 'activated' => 1, 'sendmail' => 1, 'groups' => 'users'], // invalid
208
        ];
209
    }
210
211
212
    protected function createPasswordEncoder($isPasswordValid = true)
213
    {
214
        $mock = $this->getMockBuilder(PasswordEncoderInterface::class)->getMock();
215
        $mock->method('encodePassword')->willReturn('thisIsAnEncodedPassword!');
216
217
        return $mock;
218
    }
219
220
    protected function createEncoderFactory($encoder = null)
221
    {
222
        $mock = $this->getMockBuilder(EncoderFactoryInterface::class)->getMock();
223
224
        $mock
225
            ->expects($this->any())
226
            ->method('getEncoder')
227
            ->willReturn($encoder)
228
        ;
229
230
        return $mock;
231
    }
232
233
    protected function createGroups(): array
234
    {
235
        $records = [
236
            [
237
                'gid' => GroupsConstant::GROUP_ID_USERS,
238
                'name' => 'Users',
239
                'description' => 'By default, all users are made members of this group.'
240
            ],
241
            [
242
                'gid' => GroupsConstant::GROUP_ID_ADMIN,
243
                'name' => 'Administrators',
244
                'description' => 'Group of administrators of this site.',
245
            ]
246
        ];
247
248
        $groups = [];
249
        foreach ($records as $record) {
250
            $group = new GroupEntity();
251
            $group->setGid($record['gid']);
252
            $group->setName($record['name']);
253
            $group->setDescription($record['description']);
254
            $groups[$record['gid']] = $group;
255
        }
256
257
        return $groups;
258
    }
259
}
260