Passed
Push — master ( a1fd67...e2e77c )
by Garion
04:50 queued 10s
created

EditableFormFieldTest::displayedProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 27
nc 1
nop 0
dl 0
loc 37
rs 9.488
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\UserForms\Tests\Model;
4
5
use SilverStripe\Core\Config\Config;
6
use SilverStripe\Dev\FunctionalTest;
7
use SilverStripe\Forms\DropdownField;
8
use SilverStripe\Forms\OptionsetField;
9
use SilverStripe\UserForms\Model\EditableFormField;
10
use SilverStripe\UserForms\Model\EditableFormField\EditableCheckbox;
11
use SilverStripe\UserForms\Model\EditableFormField\EditableDropdown;
12
use SilverStripe\UserForms\Model\EditableFormField\EditableFileField;
13
use SilverStripe\UserForms\Model\EditableFormField\EditableOption;
14
use SilverStripe\UserForms\Model\EditableFormField\EditableRadioField;
15
use SilverStripe\UserForms\Model\EditableFormField\EditableTextField;
16
use SilverStripe\UserForms\Model\UserDefinedForm;
17
18
/**
19
 * @package userforms
20
 */
21
class EditableFormFieldTest extends FunctionalTest
22
{
23
    protected static $fixture_file = 'EditableFormFieldTest.yml';
24
25
    public function testFormFieldPermissions()
26
    {
27
        $text = $this->objFromFixture(EditableTextField::class, 'basic-text');
28
29
        $this->logInWithPermission('ADMIN');
30
31
        $this->assertTrue($text->canCreate());
32
        $this->assertTrue($text->canView());
33
        $this->assertTrue($text->canEdit());
34
        $this->assertTrue($text->canDelete());
35
36
        $text->setReadonly(true);
37
        $this->assertTrue($text->canView());
38
        $this->assertFalse($text->canEdit());
39
        $this->assertFalse($text->canDelete());
40
41
        $text->setReadonly(false);
42
        $this->assertTrue($text->canView());
43
        $this->assertTrue($text->canEdit());
44
        $this->assertTrue($text->canDelete());
45
46
        $this->logOut();
47
        $this->logInWithPermission('SITETREE_VIEW_ALL');
48
49
        $this->assertFalse($text->canCreate());
50
51
        $text->setReadonly(false);
52
        $this->assertTrue($text->canView());
53
        $this->assertFalse($text->canEdit());
54
        $this->assertFalse($text->canDelete());
55
56
        $text->setReadonly(true);
57
        $this->assertTrue($text->canView());
58
        $this->assertFalse($text->canEdit());
59
        $this->assertFalse($text->canDelete());
60
    }
61
62
    public function testCustomRules()
63
    {
64
        $this->logInWithPermission('ADMIN');
65
        $form = $this->objFromFixture(UserDefinedForm::class, 'custom-rules-form');
66
67
        $checkbox = $form->Fields()->find('ClassName', EditableCheckbox::class);
68
        $field = $form->Fields()->find('ClassName', EditableTextField::class);
69
70
        $rules = $checkbox->DisplayRules();
71
72
        // form has 2 fields - a checkbox and a text field
73
        // it has 1 rule - when ticked the checkbox hides the text field
74
        $this->assertEquals(1, $rules->Count());
75
76
        // EffectiveDisplayRules rule has been deprecated
77
        $this->assertEquals($rules, $checkbox->EffectiveDisplayRules());
78
79
        $checkboxRule = $rules->First();
80
        $checkboxRule->ConditionFieldID = $field->ID;
81
82
        $this->assertEquals($checkboxRule->Display, 'Hide');
83
        $this->assertEquals($checkboxRule->ConditionOption, 'HasValue');
84
        $this->assertEquals($checkboxRule->FieldValue, '6');
85
86
        // If field is required then all custom rules are disabled
87
        $checkbox->Required = true;
88
        $this->assertEquals(0, $checkbox->EffectiveDisplayRules()->count());
89
    }
90
91
    public function testEditableOptionEmptyValue()
92
    {
93
        $option = $this->objFromFixture(EditableOption::class, 'option-1');
94
        $option->Value = '';
95
96
        // Disallow empty values
97
        EditableOption::set_allow_empty_values(false);
98
        $this->assertEquals($option->Title, $option->Value);
99
100
        $option->Value = 'test';
101
        $this->assertEquals('test', $option->Value);
102
103
        // Allow empty values
104
        EditableOption::set_allow_empty_values(true);
105
        $option->Value = '';
106
        $this->assertEquals('', $option->Value);
107
    }
108
109
    public function testEditableDropdownField()
110
    {
111
        $dropdown = $this->objFromFixture(EditableDropdown::class, 'basic-dropdown');
112
113
        $field = $dropdown->getFormField();
114
115
        $this->assertThat($field, $this->isInstanceOf(DropdownField::class));
116
        $values = $field->getSource();
117
118
        $this->assertEquals(['Option 1' => 'Option 1', 'Option 2' => 'Option 2'], $values);
119
    }
120
121
    public function testEditableRadioField()
122
    {
123
        $radio = $this->objFromFixture(EditableRadioField::class, 'radio-field');
124
125
        $field = $radio->getFormField();
126
127
        $this->assertThat($field, $this->isInstanceOf(OptionsetField::class));
128
        $values = $field->getSource();
129
130
        $this->assertEquals(['Option 5' => 'Option 5', 'Option 6' => 'Option 6'], $values);
131
    }
132
133
    public function testMultipleOptionDuplication()
134
    {
135
        $dropdown = $this->objFromFixture(EditableDropdown::class, 'basic-dropdown');
136
137
        $clone = $dropdown->duplicate();
138
139
        $this->assertEquals(
140
            $dropdown->Options()->Count(),
141
            $clone->Options()->Count(),
142
            "The duplicate should have contain same number of options"
143
        );
144
145
        foreach ($clone->Options() as $option) {
146
            $original = $dropdown->Options()->find('Title', $option->Title);
147
148
            $this->assertEquals($original->Sort, $option->Sort);
149
        }
150
    }
151
152
    public function testFileField()
153
    {
154
        $fileField = $this->objFromFixture(EditableFileField::class, 'file-field');
155
        $formField = $fileField->getFormField();
156
157
        $this->assertContains('jpg', $formField->getValidator()->getAllowedExtensions());
158
        $this->assertNotContains('notallowedextension', $formField->getValidator()->getAllowedExtensions());
159
    }
160
161
    public function testFileFieldAllowedExtensionsBlacklist()
162
    {
163
        Config::modify()->merge(EditableFileField::class, 'allowed_extensions_blacklist', ['jpg']);
164
        $fileField = $this->objFromFixture(EditableFileField::class, 'file-field');
165
        $formField = $fileField->getFormField();
166
167
        $this->assertNotContains('jpg', $formField->getValidator()->getAllowedExtensions());
168
    }
169
170
    /**
171
     * Verify that unique names are automatically generated for each formfield
172
     */
173
    public function testUniqueName()
174
    {
175
        $textfield1 = new EditableTextField();
176
        $this->assertEmpty($textfield1->Name);
177
178
        // Write values
179
        $textfield1->write();
180
        $textfield2 = new EditableTextField();
181
        $textfield2->write();
182
        $checkboxField = new EditableCheckbox();
183
        $checkboxField->write();
184
185
        // Test values are in the expected format
186
        $this->assertRegExp('/^EditableTextField_.+/', $textfield1->Name);
187
        $this->assertRegExp('/^EditableTextField_.+/', $textfield2->Name);
188
        $this->assertRegExp('/^EditableCheckbox_.+/', $checkboxField->Name);
189
        $this->assertNotEquals($textfield1->Name, $textfield2->Name);
190
    }
191
192
    public function testLengthRange()
193
    {
194
        /** @var EditableTextField $textField */
195
        $textField = $this->objFromFixture(EditableTextField::class, 'basic-text');
196
197
        // Empty range
198
        /** @var TextField $formField */
199
        $textField->MinLength = 0;
0 ignored issues
show
Bug Best Practice introduced by
The property MinLength does not exist on SilverStripe\UserForms\M...Field\EditableTextField. Since you implemented __set, consider adding a @property annotation.
Loading history...
200
        $textField->MaxLength = 0;
0 ignored issues
show
Bug Best Practice introduced by
The property MaxLength does not exist on SilverStripe\UserForms\M...Field\EditableTextField. Since you implemented __set, consider adding a @property annotation.
Loading history...
201
        $attributes = $textField->getFormField()->getAttributes();
202
        $this->assertFalse(isset($attributes['maxLength']));
203
        $this->assertFalse(isset($attributes['data-rule-minlength']));
204
        $this->assertFalse(isset($attributes['data-rule-maxlength']));
205
206
        // Test valid range
207
        $textField->MinLength = 10;
208
        $textField->MaxLength = 20;
209
        $attributes = $textField->getFormField()->getAttributes();
210
        $this->assertEquals(20, $attributes['maxLength']);
211
        $this->assertEquals(20, $attributes['size']);
212
        $this->assertEquals(10, $attributes['data-rule-minlength']);
213
        $this->assertEquals(20, $attributes['data-rule-maxlength']);
214
215
        // textarea
216
        $textField->Rows = 3;
0 ignored issues
show
Bug Best Practice introduced by
The property Rows does not exist on SilverStripe\UserForms\M...Field\EditableTextField. Since you implemented __set, consider adding a @property annotation.
Loading history...
217
        $attributes = $textField->getFormField()->getAttributes();
218
        $this->assertFalse(isset($attributes['maxLength']));
219
        $this->assertEquals(10, $attributes['data-rule-minlength']);
220
        $this->assertEquals(20, $attributes['data-rule-maxlength']);
221
    }
222
223
    public function testFormatDisplayRules()
224
    {
225
        $field = $this->objFromFixture(EditableTextField::class, 'irdNumberField');
226
        $displayRules = $field->formatDisplayRules();
227
        $this->assertNotNull($displayRules);
228
        $this->assertCount(1, $displayRules['operations']);
229
230
        // Field is initially visible, so the "view" method should be to hide it
231
        $this->assertSame('addClass("hide")', $displayRules['view']);
232
        // The opposite method should be to return it to its original state, i.e. show it again
233
        $this->assertSame('removeClass("hide")', $displayRules['opposite']);
234
    }
235
236
    public function testGetIcon()
237
    {
238
        $field = new EditableTextField;
239
240
        $this->assertContains('/images/editabletextfield.png', $field->getIcon());
241
    }
242
243
    public function displayedProvider()
244
    {
245
        $one = ['basic_text_name' => 'foobar'];
246
        $two = array_merge($one, ['basic_text_name_2' => 'foobar']);
247
248
        return [
249
            'no display rule AND' => ['alwaysVisible', [], true],
250
            'no display rule OR' =>  ['alwaysVisibleOr', [], true],
251
252
            'no display rule hidden AND' => ['neverVisible', [], false],
253
            'no display rule hidden OR' => ['neverVisibleOr', [], false],
254
255
            '1 unmet display rule AND' => ['singleDisplayRule', [], false],
256
            '1 met display rule AND' => ['singleDisplayRule', $one, true],
257
            '1 unmet display rule OR' => ['singleDisplayRuleOr', [], false],
258
            '1 met display rule OR' => ['singleDisplayRuleOr', $one, true],
259
260
            '1 unmet hide rule AND' => ['singleHiddingRule', [], true],
261
            '1 met hide rule AND' => ['singleHiddingRule', $one, false],
262
            '1 unmet hide rule OR' => ['singleHiddingRuleOr', [], true],
263
            '1 met hide rule OR' => ['singleHiddingRuleOr', $one, false],
264
265
            'multi display rule AND none met' => ['multiDisplayRule', [], false],
266
            'multi display rule AND partially met' => ['multiDisplayRule', $one, false],
267
            'multi display rule AND all met' => ['multiDisplayRule', $two, true],
268
269
            'multi display rule OR none met' => ['multiDisplayRuleOr', [], false],
270
            'multi display rule OR partially met' => ['multiDisplayRuleOr', $one, true],
271
            'multi display rule OR all met' => ['multiDisplayRuleOr', $two, true],
272
273
            'multi hide rule AND none met' => ['multiHiddingRule', [], true],
274
            'multi hide rule AND partially met' => ['multiHiddingRule', $one, true],
275
            'multi hide rule AND all met' => ['multiHiddingRule', $two, false],
276
277
            'multi hide rule OR none met' => ['multiHiddingRuleOr', [], true],
278
            'multi hide rule OR partially met' => ['multiHiddingRuleOr', $one, false],
279
            'multi hide rule OR all met' => ['multiHiddingRuleOr', $two, false],
280
        ];
281
    }
282
283
    /**
284
     * @param $fieldName
285
     * @param $data
286
     * @param $expected
287
     * @dataProvider displayedProvider
288
     */
289
    public function testIsDisplayed($fieldName, $data, $expected)
290
    {
291
        /** @var EditableFormField $field */
292
        $field = $this->objFromFixture(EditableTextField::class, $fieldName);
293
        $this->assertEquals($expected, $field->isDisplayed($data));
294
    }
295
}
296