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:

$form = $crawler->selectButton('submit')->form();

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 JobType class:

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 new.

Testing the Form

If the form is valid, the job should have been created and the user redirected to the preview page:

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 JobControllerTest class:

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:

Maintenance Tasks

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 (src/AppBundle/Command/JobeetCleanupCommand.php).

You will have to add the cleanup method to the JobRepository class:

To run the command execute the following from the project folder:

php app/console ens:jobeet:cleanup

or

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.


About the Author

Passionate about web & mobile development. Doing this at IntelligentBee for the last 5 years. If you are looking for custom web and mobile app development, please contact us here and let’s have a talk.