Symfony 2.8 Jobeet Day 11: Testing Your Forms
In day 10, we created our first form with Symfony. People are now able to post a new job on Jobeet but we ran out of time before we could add some tests. That’s what we will do along these lines.
Submitting a Form
Let’s open the
JobControllerTest file to add functional tests for the job creation and validation process. At the end of the file, add the following code to get the job creation page:
To select forms we will use the
selectButton() method. This method can select button tags and submit input tags. Once you have a Crawler representing a button, call the
form() method to get a
Form instance for the form wrapping the button node:
When calling the
form() method, you can also pass an array of field values that overrides the default ones:
$form = $crawler->selectButton('submit')->form(array(
'name' => 'Dragos',
'my_form[subject]' => 'Symfony Rocks!'
But to pass the field values, we need to know their names. If you open the source code or use your browser inspect element feature, you will see that the name for the company field is
appbundle_job[company]. To make things look a bit more clean, let’s change the format to
job[%s] by replacing the
getBlockPrefix method with the following code at the end of the
After this change, the company name should be
job[company] in your browser. It is now time to actually select and pass valid values to the form:
The browser also simulates file uploads if you pass the absolute path to the file to upload.
After submitting the form, we checked that the executed action is
Testing the Form
If the form is valid, the job should have been created and the user redirected to the
Testing the Database Record
Eventually, we want to test that the job has been created in the database and check that the
isActivated column is set to
false as the user has not published it yet.
Testing for Errors
The job form creation works as expected when we submit valid values. Let’s add a test to check the behaviour when we submit non-valid data:
Now, we need to test the admin bar found on the job preview page. When a job has not been activated yet, you can edit, delete, or publish the job. To test those three actions, we will need to first create a job. But that’s a lot of copy and paste, so let’s add a job creator method in the
createJob() method creates a job, follows the redirect and returns the browser. You can also pass an array of values that will be merged with some default values.
Testing the “Publish” action is now more simple:
Testing the “Delete” action is quite similar:
Tests as a SafeGuard
When a job is published, you cannot edit it anymore. Even if the “Edit” link is not displayed anymore on the preview page, let’s add some tests for this requirement.
First, add another argument to the
createJob() method to allow automatic publication of the job, and create a
getJobByPosition() method that returns a job given its position value:
If a job is published, the edit page must return a 404 status code:
But if you run the tests, you won’t have the expected result as we forgot to implement this security measure yesterday. Writing tests is also a great way to discover bugs, as you need to think about all edge cases.
Fixing the bug is quite simple as we just need to forward to a 404 page if the job is activated:
Back to the Future in a Test
When a job is expiring in less than five days, or if it is already expired, the user can extend the job validation for another 30 days from the current date.
Testing this requirement in a browser is not easy as the expiration date is automatically set when the job is created to 30 days in the future. So, when getting the job page, the link to extend the job is not present. Sure, you can hack the expiration date in the database, or tweak the template to always display the link, but that’s tedious and error prone. As you have already guessed, writing some tests will help us one more time.
As always, we need to add a new extend action and form first:
Then, replace the “Extend” link code in the _admin partial with the extend form:
Also, add the extend form to the preview action:
As expected by the action, the
extend() method of Job returns true if the job has been extended or false otherwise:
Eventually, add a test scenario:
Even if symfony is a web framework, it comes with a command line tool. You have already used it to create the default directory structure of the application bundle and to generate various files for the model. Adding a new command is quite easy.
When a user creates a job, he must activate it to put it online. But if not, the database will grow with stale jobs. Let’s create a command that remove stale jobs from the database. This command will have to be run regularly in a cron job (
You will have to add the
cleanup method to the
To run the command execute the following from the project folder:
php app/console ens:jobeet:cleanup
php app/console ens:jobeet:cleanup 10
to delete stale jobs older than 10 days.
That’s all for now. Get the code from day 11 here: https://github.com/dragosholban/jobeet-sf2.8/tree/day11.