Cypress tests organizing (or any e2e/ui tests)

Nowadays cypress is quite a hype technology (I am saying this in Fall 2020, everyone knows how rapidly js world can change ;))

"Cypress is a next generation front end testing tool built for the modern web."

https://docs.cypress.io/guides/overview/why-cypress.html#In-a-nutshel

I had some experience with Behat and other types of tests like unit/integarational, but today I will tell you about e2e.

When I wrote Behat tests I didn't think a lot about how to structure my test cases in a maintainable way. This led me to the antipattern called "Single-Layer Architecture"[1].

Extending such tests quickly becomes a mess and tends to become an ineffective work:

  1. You can't focus on business logic, you always need to remember low-level details to introduce a new step definition
  2. Your low-level solutions are often duplicated, and you even don't notice that
  3. Changing testing framework means rewriting or updating all step definitions!

Fortunately there is an approach which is very easy to follow and which mitigates mentioned issues.

Continuous integration using Travis CI and Behat

This note begins a series of notes on application development and deployment processes. To start with, I will show how you can relatively easily implement a code quality and functionality checking process using the Travis CI service.

The practice of continuously checking the build for defects is called Continuous Integration.

The question of writing tests will not be addressed in this article - it is the subject of another article. It is assumed that you have already set up Behat, and the tests can already be run locally using Selenium.

To begin with, let's check if there are any rule violations in the code. This will allow you to familiarize yourself with and start using Travis CI. If you don't have any tests, I strongly recommend at least checking the code style.
The justification for the importance of code consistency and style can be found in many places, for example, Steve McConnell's "Code Complete", part 7, section 31.

How to find the line on which execution was interrupted in PHP

When working with old code, it is sometimes very difficult to find the place where execution was interrupted. Constructions like die, exit, etc. are very bad practice, but there is a lot of legacy code (and not only - I'm not saying anything bad about Wordpress, so I'll keep quiet) that abuse them. One of the biggest problems with such constructions is that they are difficult to find and debug. (Use exceptions!)

But when the task is to find the place where code execution is interrupted, you can use the following snippet:

Refreshing Nested Set Tree Indexes in Symfony

Tree

Once I used Nestedset behavior for Doctrine, Symfony in a project, and faced issue with broken indexes. (You can read how Nested Set works here). This happened because low-level MySQL query executed during migration, and because of this Doctrine events responsible for refreshing indexes was not executed. To fix that a Symfony Command was written, which refreshes indexes. This is just example. Better way is to move this code to the service and add one more migration which will refresh indexes. Here is just simple example how this issue can be solved.

Argument of the command is an entity to refresh.

Uploading files in Symfony

Uploading files in Symfony is conceptually no different from other PHP platforms, but still has its own features due to the presence of additional tools provided by the framework.

First of all, it is worth noting that there are ready-made solutions that solve the task at hand. I strongly recommend familiarizing yourself with them, and only after that, if you decide that they do not suit you, implement your own solution.

In this note we will try to show possible ways to solve the task, using both ready-made solutions (VichUploaderBundle, IphpFileStoreBundle), and using our own implementation (in Symfony controllers and admin classes from the SonataAdminBundle).

Adding comments to the website

Honestly, when I saw that they write about it and give advice to beginners on other sites, I was a little horrified and decided to create my own note on this topic without a "fatal flaw". Mostly, I saw long pieces of code that implement adding comments to a site. Usually, for this, a form is created, its processing, storage, and also selection for display are implemented. But the advantages of such an approach are diminishing over time.

In this note, you will learn one of the simplest (but subjectively one of the most preferred) ways to add comments to a site - a simple example for beginners + options for more advanced webmasters.

Indeed, why invent the bicycle and write a lot of code that will have to be maintained, fixed, etc. in the future, if there are plenty of ready-made solutions from third-party services (we are talking about social networks + disqus)?

Asset versioning when using gulp

assetsWhen changing client code, you need to somehow force the client's browser to reload the modified files. This problem is quite common. Most likely, you will encounter it regardless of the technologies you use in web development. This example is about solving the problem when creating a frontend project using JavaScript and Gulp.

You can solve it in several ways.

Let's say, for example, 7e50961489 is the new version of the assets. Actually, it can be any version, the main thing is that it should be different from the previous ones. You can simply number them - 1, 2, 3, etc. But it's not very convenient. Later it will be clear why.

Gulp file for frontend project

The solution is not perfect. But it is suitable for developing a small frontend project written in coffeescript and less. Important note: the use of backend is not provided. Nodejs is only used for building assets (this solution is convenient, for example, if you plan to create a hybrid offline application for smartphones).

The key features of our project, and as a result, the gulp file:

1) Supports different environments (prod, dev, etc)

2) Compilation and minification of less, CoffeScript files, combining multiple into one (concatenation)

3) Support for tests (jasmine)

4) In the dev environment, watch is functioning (dynamically rebuilds assets when source files are changed)

Remove the default block sonata.admin.block.admin_list in SonataAdminBundle.

When using SonataAdminBundle and SonataBlockBundle, I wanted to remove the default block.

It doesn't provide much benefit, as it simply duplicates the functionality of the side menu on the dashboard.

When installing SonataBlockBundle, if we simply write in the configuration:

sonata_block:
    default_contexts: [sonata_page_bundle]
    blocks: []

(in the future we will add our own blocks, but for now we just leave an empty array), we will catch an error.

Iteration over a time period in PHP

Repeatedly had to work with a list of dates on php (by days, for example) if there is a start and end of the period ($dateStart, $dateEnd). For example, to synchronize working/non-working days for the DatePicker from jQueryUi with the backend. Or if you need to display reports by days.

I suggest several options for solving this problem, both the most obvious way and a more elegant way (as it seemed to me).

Caching Symfony controller

During developing this blog I invented one more bicycle for Caching Symfony controller. But first of all lets see how did this task arose.

For example, I have a list of categories, archives and tags on a sidebar. It is relatively easy to get last one (one query), but much harder to get list of categories and archives. For getting categories, we need to select trees (categories can be nested) and using subqueries inside queries get number of articles in every category (result is a little bit monster). For getting the archives list, we need iterate over all articles and gather list of years/months. All this actions isn't very sophisticated, but it is better to avoid them.

Sleep in Qt

Somehow got very distracted from Qt. And then the other day had to come back =) Spent a long time remembering how I used to implement delays, or sleep in Qt (yes, yes, yes, it's bad, etc., but sometimes you really need it, especially if you need to turn in a lab to make others stop bothering you.)

Example of a trivial implementation:

Setting PHP timezone in php.ini

During the work with Symfony framework, I received the following warning:

Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /var/www/symfony/app/cache/prod/classes.php on line 5009

In fact, there is nothing to worry about or unusual - this was caused by updating PHP to version 5.4, and since the new version was installed next to the old one with new configs, it was necessary to configure the PHP timezone in php.ini again. First, we need to find out which timezone we are in. More precisely, how it should be specified in the PHP config.