Simpler times

A little Cypress

I am currently working as a teacher for Generalitat Valenciana. It's always been said that teachers have a lot of paperwork. It is not my case, but it could be because I work in vocational training: we fill a curriculum design at the start of the school year (which nobody reads) and not much else.

However, there are two things I must do every day. The first is the roll call: I must register in a Generalitat’s application who has attend the class and who hasn't. The second is to put on record that I’ve been there teaching the class. It might sound weird, but the reason is the school receives money from CE development initiatives for each day I attend . My school knows which days I’ve been there , but I'm the one who must leave a written record ; I think it’s a fraud prevention measure.

Each day that I do something that has no clear value, my little DevOps’ heart is torn apart and I that makes me think how to automate that process. I see the value of calling the roll, but not the value of marking my assistance. I've been thinking about automating it for years, but the check to mark my assistance is on the same web page as the roll call and it is easy to mark it; it seemed to me that automating it will give me more work than I would save, but the school has implemented a new system to revise the missing checks which are giving me additional work, so I think it is time to do it.

To automate it I’ve chosen Cypress. It’s a testing tool, not an automation one. In its documentation, they warn about using Cypress for testing pages we don’t own, but it’s a tool I’m interested in learning so I’ll give it a try.

Installing Cypress is simple, we only need to `npm install cypress` and then we can run it with `npx cypress open`. It comes with a couple of examples of test that you can run against a Cypress.io web page.

I thought it would be simple to automate login. The login screen is like this:

Image of login form

Opening the page was simple:


it('Opens the login page', function() {
        cy.visit('https://docent.edu.gva.es')
        cy.contains('DNI/NIE')
        cy.contains('Contraseña')
    })

The first problem I encountered was with field selection. The user and name fields have weird names (`form1:j_username` and `form1:j_password`) You can select them with `document.getElementById(‘form1:j_username’)`. The equivalent instruction in Cypress is `cy.get`, but when you try to do the same you get an error:


cy.get('#form1:j_username')
Error: Syntax error, unrecognized expression: unsupported pseudo: j_username

I couldn’t find a way to “escape” the colon, and I needed to use a workaround: cy.get(‘[id$="j_username"]’).

The second problem was typing. I stored the fields in variables and then tried to type into the field (to my surprise, you have to declare the variables):


const USERNAME_SEL = '[id$="j_username"]'
const PASSWORD_SEL = '[id$="j_password"]'

let username = cy.get(USERNAME_SEL)
let password = cy.get(PASSWORD_SEL)

username.type('banana')
username.type('potato')

Cypress only typed in the second field:

Image of Cypress filling only one of the fields

I think there is a reason for that, but it was simpler to chain selection and typing and avoid the variables:


cy.get(USERNAME_SEL).type(Cypress.env('USER'))
cy.get(PASSWORD_SEL).type(Cypress.env('PASSWORD'))

I stored username and password in cypress.env.json file, placed at the application’s root directory. That file should not be checked into git, because it has sensitive information.

The last problem I found was the login action. I thought it would be as simple as clicking the button:


const LOGIN_BUTTON_SEL = 'input[type="submit"][value="Entrar"]'
cy.get(LOGIN_BUTTON_SEL).click()

But Cypress wasn’t able to load the page. There is some kind of SSO system: when you log in with the POST request, you get a 302 redirection response and Cypress is not able to manage it.

I tried to solve it in a couple of ways, but after a bit of searching was unable to do so. At this point I stopped: my idea was to learn a little bit of Cypress trying to automate a process, but it's clearly not the right tool for the job (as it’s said in the documentation!)

I thought Cypress would perform simple web browser automation, but it seems it does much more than just send keystrokes and interact with page elements. It is not a “transparent” tool, so you don’t have the same behaviour as you would have with a real web page. Maybe it causes weird errors testing web pages, or maybe it doesn’t catch errors which would occur in production, but it’s a widely used tool so, if it happens, it would be in rare occasions.

To continue with the task I should use another tool like Selenium Python Web driver: it seems that it is a simple automation tool which can be integrated with a test framework. But I think learning that won’t be very helpful to me, so I’ll spend my time with a technology I will need earlier: Progressive Web Applications.