Issues (3627)

Constraints/CircularDependencyValidatorTest.php (1 issue)

1
<?php
2
3
namespace Mautic\CoreBundle\Tests\Unit\Form\Validator\Constraints;
4
5
use Mautic\CoreBundle\Form\Validator\Constraints\CircularDependency;
6
use Mautic\CoreBundle\Form\Validator\Constraints\CircularDependencyValidator;
7
use Mautic\LeadBundle\Entity\LeadList;
8
use Mautic\LeadBundle\Model\ListModel;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\HttpFoundation\RequestStack;
11
use Symfony\Component\Validator\Context\ExecutionContext;
12
13
class CircularDependencyValidatorTest extends \PHPUnit\Framework\TestCase
14
{
15
    /**
16
     * @var \PHPUnit\Framework\MockObject\MockObject|ListModel
17
     */
18
    private $mockListModel;
19
20
    /**
21
     * @var \PHPUnit\Framework\MockObject\MockObject|ExecutionContext
22
     */
23
    private $context;
24
25
    /**
26
     * @var \PHPUnit\Framework\MockObject\MockObject|RequestStack
27
     */
28
    private $requestStack;
29
30
    /**
31
     * @var \PHPUnit\Framework\MockObject\MockObject|Request
32
     */
33
    private $request;
34
35
    /**
36
     * @var CircularDependencyValidator
37
     */
38
    private $validator;
39
40
    protected function setUp(): void
41
    {
42
        parent::setUp();
43
44
        $this->mockListModel = $this->createMock(ListModel::class);
45
        $this->context       = $this->createMock(ExecutionContext::class);
46
        $this->requestStack  = $this->createMock(RequestStack::class);
47
        $this->request       = $this->createMock(Request::class);
48
49
        $this->requestStack->expects($this->once())
50
            ->method('getCurrentRequest')
51
            ->willReturn($this->request);
52
53
        $this->validator = new CircularDependencyValidator($this->mockListModel, $this->requestStack);
54
        $this->validator->initialize($this->context);
55
    }
56
57
    /**
58
     * Checks that the validator won't break if the segment ID is not present in the request.
59
     */
60
    public function testIfSegmentIdIsNotInTheRequest()
61
    {
62
        $this->context->expects($this->never())
63
            ->method('addViolation');
64
65
        $this->mockListModel->expects($this->never())
66
            ->method('getEntity');
67
68
        $this->validator->validate([], new CircularDependency([]));
69
    }
70
71
    /**
72
     * Configure a CircularDependencyValidator.
73
     *
74
     * @param string $expectedMessage  the expected message on a validation violation, if any
75
     * @param int    $currentSegmentId
76
     *
77
     * @return Mautic\CoreBundle\Form\Validator\Constraints\CircularDependencyValidator
0 ignored issues
show
The type Mautic\CoreBundle\Tests\...ularDependencyValidator was not found. Did you mean Mautic\CoreBundle\Form\V...ularDependencyValidator? If so, make sure to prefix the type with \.
Loading history...
78
     */
79
    private function configureValidator($expectedMessage, $currentSegmentId)
80
    {
81
        $filters = [
82
            [
83
                'glue'     => 'and',
84
                'field'    => 'leadlist',
85
                'object'   => 'lead',
86
                'type'     => 'leadlist',
87
                'filter'   => [2],
88
                'display'  => null,
89
                'operator' => 'in',
90
            ],
91
        ];
92
93
        $filters2 = [
94
            [
95
                'glue'     => 'and',
96
                'field'    => 'leadlist',
97
                'object'   => 'lead',
98
                'type'     => 'leadlist',
99
                'filter'   => [1],
100
                'display'  => null,
101
                'operator' => 'in',
102
            ],
103
        ];
104
105
        $filters3 = [
106
            [
107
                'glue'     => 'and',
108
                'field'    => 'first_name',
109
                'object'   => 'lead',
110
                'type'     => 'text',
111
                'filter'   => 'John',
112
                'display'  => null,
113
                'operator' => '=',
114
            ],
115
        ];
116
117
        $mockEntity1 = $this->createMock(LeadList::class);
118
        $mockEntity1->expects($this->any())
119
            ->method('getId')
120
            ->willReturn(1);
121
        $mockEntity1->expects($this->any())
122
            ->method('getFilters')
123
            ->willReturn($filters);
124
125
        $mockEntity2 = $this->createMock(LeadList::class);
126
        $mockEntity2->expects($this->any())
127
            ->method('getId')
128
            ->willReturn(2);
129
        $mockEntity2->expects($this->any())
130
            ->method('getFilters')
131
            ->willReturn($filters2);
132
133
        $mockEntity3 = $this->createMock(LeadList::class);
134
        $mockEntity3->expects($this->any())
135
            ->method('getId')
136
            ->willReturn(3);
137
        $mockEntity3->expects($this->any())
138
            ->method('getFilters')
139
            ->willReturn($filters3);
140
141
        $entities = [
142
            1 => $mockEntity1,
143
            2 => $mockEntity2,
144
            3 => $mockEntity3,
145
        ];
146
147
        $this->mockListModel->expects($this->any())
148
            ->method('getEntity')
149
            ->willReturnCallback(function ($id) use ($entities) {
150
                return $entities[$id];
151
            });
152
153
        if (!empty($expectedMessage)) {
154
            $this->context->expects($this->once())
155
                ->method('addViolation')
156
                ->with($this->equalTo($expectedMessage));
157
        } else {
158
            $this->context->expects($this->never())
159
                ->method('addViolation');
160
        }
161
162
        $this->request->expects($this->once())
163
            ->method('get')
164
            ->with('_route_params')
165
            ->willReturn([
166
                'objectId' => $currentSegmentId,
167
            ]);
168
169
        return $this->validator;
170
    }
171
172
    /**
173
     * Verify a constraint message.
174
     *
175
     * @dataProvider validateDataProvider
176
     */
177
    public function testValidateOnInvalid($message, $currentSegmentId, $filters)
178
    {
179
        $this->configureValidator($message, $currentSegmentId)
180
            ->validate($filters, new CircularDependency(['message' => 'mautic.core.segment.circular_dependency_exists']));
181
    }
182
183
    public function validateDataProvider()
184
    {
185
        $constraint = new CircularDependency(['message' => 'mautic.core.segment.circular_dependency_exists']);
186
187
        return [
188
            // Segment 1 is dependent on Segment 2 which is dependent on segment 1 - circular
189
            [
190
                $constraint->message,
191
                2, // current segment id
192
                [
193
                    [
194
                        'glue'     => 'and',
195
                        'field'    => 'leadlist',
196
                        'object'   => 'lead',
197
                        'type'     => 'leadlist',
198
                        'filter'   => [1],
199
                        'display'  => null,
200
                        'operator' => 'in',
201
                    ],
202
                ],
203
            ],
204
            // Segment 2 is dependent on Segment 1 which is dependent on segment 2 - circular
205
            [
206
                $constraint->message,
207
                1, // current segment id
208
                [
209
                    [
210
                        'glue'     => 'and',
211
                        'field'    => 'leadlist',
212
                        'object'   => 'lead',
213
                        'type'     => 'leadlist',
214
                        'filter'   => [2],
215
                        'display'  => null,
216
                        'operator' => 'in',
217
                    ],
218
                ],
219
            ],
220
            // Test when there are no validation errors
221
            // The segment in the filter (3) is NOT dependent on any
222
            [
223
                null,
224
                1, // current segment id
225
                [
226
                    [
227
                        'glue'     => 'and',
228
                        'field'    => 'leadlist',
229
                        'object'   => 'lead',
230
                        'type'     => 'leadlist',
231
                        'filter'   => [3],
232
                        'display'  => null,
233
                        'operator' => 'in',
234
                    ],
235
                ],
236
            ],
237
            // Test when no lead list filters
238
            [
239
                null,
240
                1, // current segment id
241
                [
242
                    [
243
                        'glue'     => 'and',
244
                        'field'    => 'first_name',
245
                        'object'   => 'lead',
246
                        'type'     => 'text',
247
                        'filter'   => 'Doe',
248
                        'display'  => null,
249
                        'operator' => '=',
250
                    ],
251
                ],
252
            ],
253
            // Test multiple lead list filters. Fails because 2 is dependent on 1
254
            [
255
                $constraint->message,
256
                2, // current segment id
257
                [
258
                    [
259
                        'glue'     => 'and',
260
                        'field'    => 'leadlist',
261
                        'object'   => 'lead',
262
                        'type'     => 'leadlist',
263
                        'filter'   => [1],
264
                        'display'  => null,
265
                        'operator' => 'in',
266
                    ],
267
                    [
268
                        'glue'     => 'and',
269
                        'field'    => 'leadlist',
270
                        'object'   => 'lead',
271
                        'type'     => 'leadlist',
272
                        'filter'   => [3],
273
                        'display'  => null,
274
                        'operator' => 'in',
275
                    ],
276
                ],
277
            ],
278
            // @TODO: MUST ADD TEST CASES ONCE WE FIX DEEP CIRCULAR (1 depends on 2 which depends on 3 which depends on 1) TO AN ARBITRARY DEPTH
279
        ];
280
    }
281
}
282