Completed
Push — master ( 82acc4...deba42 )
by Will
13s
created

UserDefinedFormControllerTest::testForm()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 12
nc 1
nop 0
1
<?php
2
3
namespace SilverStripe\UserForms\Tests\Control;
4
5
use SilverStripe\Core\Config\Config;
6
use SilverStripe\Dev\CSSContentParser;
7
use SilverStripe\Dev\FunctionalTest;
8
use SilverStripe\Dev\TestOnly;
9
use SilverStripe\Forms\FieldList;
10
use SilverStripe\Forms\FormAction;
11
use SilverStripe\ORM\DataObject;
12
use SilverStripe\Security\Member;
13
use SilverStripe\UserForms\Model\EditableFormField\EditableTextField;
14
use SilverStripe\UserForms\Model\Submission\SubmittedFormField;
15
use SilverStripe\UserForms\Model\UserDefinedForm;
16
use SilverStripe\UserForms\Control\UserDefinedFormController;
17
use SilverStripe\View\ArrayData;
18
use SilverStripe\View\SSViewer;
19
20
/**
21
 * @package userforms
22
 */
23
class UserDefinedFormControllerTest extends FunctionalTest
24
{
25
    protected static $fixture_file = '../UserFormsTest.yml';
26
27
    protected static $use_draft_site = true;
28
29
    protected function setUp()
30
    {
31
        parent::setUp();
32
33
        Config::modify()->set(SSViewer::class, 'themes', ['simple', '$default']);
34
    }
35
36
    public function testProcess()
37
    {
38
        $form = $this->setupFormFrontend();
39
40
        $controller = new UserDefinedFormController($form);
0 ignored issues
show
Unused Code introduced by
$controller is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
41
42
        $this->autoFollowRedirection = false;
43
        $this->clearEmails();
44
45
        // load the form
46
        $this->get($form->URLSegment);
47
48
        $field = $this->objFromFixture(EditableTextField::class, 'basic-text');
49
50
        $response = $this->submitForm('UserForm_Form_' . $form->ID, null, [$field->Name => 'Basic Value']);
51
52
        // should have a submitted form field now
53
        $submitted = DataObject::get(SubmittedFormField::class, "\"Name\" = 'basic-text-name'");
54
        $this->assertDOSAllMatch(
55
            [
56
                'Name' => 'basic-text-name',
57
                'Value' => 'Basic Value',
58
                'Title' => 'Basic Text Field'
59
            ],
60
            $submitted
61
        );
62
63
        // check emails
64
        $this->assertEmailSent('[email protected]', '[email protected]', 'Email Subject');
65
        $email = $this->findEmail('[email protected]', '[email protected]', 'Email Subject');
66
67
        // assert that the email has the field title and the value html email
68
        $parser = new CSSContentParser($email['Content']);
69
        $title = $parser->getBySelector('strong');
70
71
        $this->assertEquals('Basic Text Field', (string) $title[0], 'Email contains the field name');
72
73
        $value = $parser->getBySelector('dd');
74
        $this->assertEquals('Basic Value', (string) $value[0], 'Email contains the value');
75
76
        // no html
77
        $this->assertEmailSent('[email protected]', '[email protected]', 'Email Subject');
78
        $nohtml = $this->findEmail('[email protected]', '[email protected]', 'Email Subject');
79
80
        $this->assertContains('Basic Text Field: Basic Value', $nohtml['Content'], 'Email contains no html');
81
82
        // no data
83
        $this->assertEmailSent('[email protected]', '[email protected]', 'Email Subject');
84
        $nodata = $this->findEmail('[email protected]', '[email protected]', 'Email Subject');
85
86
        $parser = new CSSContentParser($nodata['Content']);
87
        $list = $parser->getBySelector('dl');
88
89
        $this->assertFalse(isset($list[0]), 'Email contains no fields');
90
91
        // check to see if the user was redirected (301)
92
        $this->assertEquals($response->getStatusCode(), 302);
93
        $this->assertStringEndsWith('finished#uff', $response->getHeader('Location'));
94
    }
95
96
    public function testValidation()
97
    {
98
        $form = $this->setupFormFrontend('email-form');
99
100
        // Post with no fields
101
        $this->get($form->URLSegment);
102
        $response = $this->submitForm('UserForm_Form_' . $form->ID, null, []);
0 ignored issues
show
Unused Code introduced by
$response is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
103
        $this->assertPartialMatchBySelector(
104
            '.field .message',
105
            ['This field is required']
106
        );
107
108
        // Post with all fields, but invalid email
109
        $this->get($form->URLSegment);
110
        $this->submitForm('UserForm_Form_' . $form->ID, null, [
111
            'required-email' => 'invalid',
112
            'required-text' => 'bob'
113
        ]);
114
        $this->assertPartialMatchBySelector(
115
            '.field .message',
116
            ['Please enter an email address']
117
        );
118
119
        // Post with only required
120
        $this->get($form->URLSegment);
121
        $this->submitForm('UserForm_Form_' . $form->ID, null, [
122
            'required-text' => 'bob'
123
        ]);
124
        $this->assertPartialMatchBySelector(
125
            'p',
126
            ["Thanks, we've received your submission."]
127
        );
128
    }
129
130 View Code Duplication
    public function testFinished()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
131
    {
132
        $form = $this->setupFormFrontend();
133
134
        // set formProcessed and SecurityID to replicate the form being filled out
135
        $this->session()->set('SecurityID', 1);
136
        $this->session()->set('FormProcessed', 1);
137
138
        $response = $this->get($form->URLSegment.'/finished');
139
140
        $this->assertContains($form->OnCompleteMessage, $response->getBody());
141
    }
142
143 View Code Duplication
    public function testAppendingFinished()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
    {
145
        $form = $this->setupFormFrontend();
146
147
        // replicate finished being added to the end of the form URL without the form being filled out
148
        $this->session()->set('SecurityID', 1);
149
        $this->session()->set('FormProcessed', null);
150
151
        $response = $this->get($form->URLSegment.'/finished');
152
153
        $this->assertNotContains($form->OnCompleteMessage, $response->getBody());
154
    }
155
156
    public function testForm()
157
    {
158
        $form = $this->objFromFixture(UserDefinedForm::class, 'basic-form-page');
159
160
        $controller = new UserDefinedFormController($form);
161
162
        // test form
163
        $this->assertEquals($controller->Form()->getName(), 'Form_' . $form->ID, 'The form is referenced as Form');
0 ignored issues
show
Bug introduced by
Consider using $controller->Form()->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
164
        $this->assertEquals($controller->Form()->Fields()->Count(), 1); // disabled SecurityID token fields
165
        $this->assertEquals($controller->Form()->Actions()->Count(), 1);
166
        $this->assertEquals(count($controller->Form()->getValidator()->getRequired()), 0);
167
168
        $requiredForm = $this->objFromFixture(UserDefinedForm::class, 'validation-form');
169
        $controller = new UserDefinedFormController($requiredForm);
170
171
        $this->assertEquals($controller->Form()->Fields()->Count(), 1); // disabled SecurityID token fields
172
        $this->assertEquals($controller->Form()->Actions()->Count(), 1);
173
        $this->assertEquals(count($controller->Form()->getValidator()->getRequired()), 1);
174
    }
175
176
    public function testGetFormFields()
177
    {
178
        // generating the fieldset of fields
179
        $form = $this->objFromFixture(UserDefinedForm::class, 'basic-form-page');
180
181
        $controller = new UserDefinedFormController($form);
182
183
        $formSteps = $controller->Form()->getFormFields();
184
        $firstStep = $formSteps->first();
185
186
        $this->assertEquals($formSteps->Count(), 1);
187
        $this->assertEquals($firstStep->getChildren()->Count(), 1);
188
189
        // custom error message on a form field
190
        $requiredForm = $this->objFromFixture(UserDefinedForm::class, 'validation-form');
191
        $controller = new UserDefinedFormController($requiredForm);
192
193
        Config::modify()->set(UserDefinedForm::class, 'required_identifier', '*');
194
195
        $formSteps = $controller->Form()->getFormFields();
196
        $firstStep = $formSteps->first();
197
        $firstField = $firstStep->getChildren()->first();
198
199
        $this->assertEquals('Custom Error Message', $firstField->getCustomValidationMessage());
200
        $this->assertEquals($firstField->Title(), 'Required Text Field <span class=\'required-identifier\'>*</span>');
201
202
        // test custom right title
203
        $field = $form->Fields()->limit(1, 1)->First();
0 ignored issues
show
Bug introduced by
The method Fields() does not exist on SilverStripe\ORM\DataObject. Did you maybe mean beforeUpdateCMSFields()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
204
        $field->RightTitle = 'Right Title';
205
        $field->write();
206
207
        $controller = new UserDefinedFormController($form);
208
        $formSteps = $controller->Form()->getFormFields();
209
        $firstStep = $formSteps->first();
210
211
        $this->assertEquals($firstStep->getChildren()->First()->RightTitle(), "Right Title");
212
213
        // test empty form
214
        $emptyForm = $this->objFromFixture(UserDefinedForm::class, 'empty-form');
215
        $controller = new UserDefinedFormController($emptyForm);
216
217
        $this->assertFalse($controller->Form()->getFormFields()->exists());
218
    }
219
220
    public function testGetFormActions()
221
    {
222
        // generating the fieldset of actions
223
        $form = $this->objFromFixture(UserDefinedForm::class, 'basic-form-page');
224
225
        $controller = new UserDefinedFormController($form);
226
        $actions = $controller->Form()->getFormActions();
227
228
        // by default will have 1 submit button which links to process
229
        $expected = new FieldList(new FormAction('process', 'Submit'));
230
        $expected->setForm($controller->Form());
231
232
        $this->assertEquals($actions, $expected);
233
234
        // the custom popup should have a reset button and a custom text
235
        $custom = $this->objFromFixture(UserDefinedForm::class, 'form-with-reset-and-custom-action');
236
        $controller = new UserDefinedFormController($custom);
237
        $actions = $controller->Form()->getFormActions();
238
239
        $expected = new FieldList(new FormAction('process', 'Custom Button'));
240
        $expected->push(FormAction::create('clearForm', 'Clear')->setAttribute('type', 'reset'));
241
        $expected->setForm($controller->Form());
242
243
        $this->assertEquals($actions, $expected);
244
    }
245
246
    public function testRenderingIntoFormTemplate()
247
    {
248
        $form = $this->setupFormFrontend();
249
250
        $this->logInWithPermission('ADMIN');
251
        $form->Content = 'This is some content without a form nested between it';
252
        $form->publishRecursive();
253
254
        $controller = new UserDefinedFormController($form);
255
256
        // check to see if $Form is replaced to inside the content
257
        $index = new ArrayData($controller->index());
258
        $parser = new CSSContentParser($index->renderWith(__CLASS__));
259
260
        $this->checkTemplateIsCorrect($parser, $form);
261
    }
262
263
    public function testRenderingIntoTemplateWithSubstringReplacement()
264
    {
265
        $form = $this->setupFormFrontend();
266
267
        $controller = new UserDefinedFormController($form);
268
269
        // check to see if $Form is replaced to inside the content
270
        $index = new ArrayData($controller->index());
271
        $parser = new CSSContentParser($index->renderWith(__CLASS__));
272
273
        $this->checkTemplateIsCorrect($parser, $form);
274
    }
275
    /**
276
     * Publish a form for use on the frontend
277
     *
278
     * @param string $fixtureName
279
     * @return UserDefinedForm
280
     */
281
    protected function setupFormFrontend($fixtureName = 'basic-form-page')
282
    {
283
        $form = $this->objFromFixture(UserDefinedForm::class, $fixtureName);
284
        $this->logInWithPermission('ADMIN');
285
286
        $form->publishRecursive();
287
288
        $member = Member::currentUser();
0 ignored issues
show
Deprecated Code introduced by
The method SilverStripe\Security\Member::currentUser() has been deprecated with message: 5.0.0 use Security::getCurrentUser()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
289
        $member->logOut();
290
291
        return $form;
292
    }
293
294
    public function checkTemplateIsCorrect($parser, $form)
295
    {
296
        $this->assertArrayHasKey(0, $parser->getBySelector('form#UserForm_Form_' . $form->ID));
297
298
        // check for the input
299
        $this->assertArrayHasKey(0, $parser->getBySelector('input.text'));
300
301
        // check for the label and the text
302
        $label = $parser->getBySelector('label.left');
303
        $this->assertArrayHasKey(0, $label);
304
305
        $this->assertEquals((string) $label[0][0], "Basic Text Field", "Label contains correct field name");
306
307
        // check for the action
308
        $action = $parser->getBySelector('input.action');
309
        $this->assertArrayHasKey(0, $action);
310
311
        $this->assertEquals((string) $action[0]['value'], "Submit", "Submit button has default text");
312
    }
313
}
314