Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cypress Angular When Can Test Start?

I'm using Cypress to do end-to-end testing on my Angular application. One source of flake that I have observed is that Cypress is fast to act and my application is (relatively) slow to become ready for interaction. Cypress has some oft-referenced blog posts that discuss this quandary.

The example in one of the blog posts suggests hijacking the addEventListener to handle a very specific example. But what I am looking for is the appropriate "sledgehammer" for Angular... anyone have any bright ideas / techniques that don't involve adding a 10 second wait to every page visit before engaging test activity (which by the way does work)? I have spent considerable time Googling to no avail. Thanks in advance for your ideas!

Aside: I've also found this open issue that, were it to be resolved fruitfully might be part of the answer.

like image 591
vicatcu Avatar asked Nov 17 '20 17:11

vicatcu


People also ask

Can Cypress be used for Angular application?

That being said, this guide recommends to use Cypress for testing Angular applications. Cypress is well-maintained and well-documented. With Cypress, you can write valuable end-to-end tests with little effort. In case you do need a WebDriver-based framework, have a look at Webdriver.io instead.

Can we use testing with Cypress?

One major difference is that Cypress enables you to write your unit tests and integration tests in the same tool, as opposed to splitting up this work across both Karma and Protractor. Also, Protractor is very much focused on AngularJS , whereas Cypress is designed to work with any JavaScript framework.

Is Cypress end-to-end testing?

Cypress is my tool of choice for debugging end-to-end tests quickly, stably, and efficiently, and for running them parallel to any pull request as part of CI. The learning curve is gentle if you're already familiar with JavaScript.


1 Answers

I've encountered this issue myself and we've tried many different things at work on our app. Even though it's something which needs to be adapted, we're quite happy with our current solution.

But before I get to the solution, let me explain why this is a hard problem to solve without simply having a long wait before we start testing.

First of all, we need to wait for our page to be ready. Luckily for us, Cypress does that for us.

Then, we could wait for Angular to be bootstraped. One way of being aware of that is by checking if getAllAngularRootElements is available on the window object. And yes this function is apparently there even in prod mode!

  cy.window()
    .its('getAllAngularRootElements' as any)
    .should('exist');

But this isn't a perfect solution especially if... You use lazy loading.

Just because Angular bootstraped your app doesn't mean all your lazy modules are loaded! And this is where it gets really unlikely to find an automatic way of waiting for exactly what you want to be ready.

So how do we start testing as soon as we can and in a safe way? In my opinion the best option to do so is to have a check after every cy.visit call and wait for one element around what you're about to test, to exist. Example:

cy.visit(`some-page`);

cy.get(
  '.some-class-around-what-I-want-to-test',
  { timeout: 15000 }
).should('exist');

// ... rest of the test goes here

The code above will load the page, wait for the element you're targetting to exist for a maximum of 15 seconds but the important thing to note is that as soon as this element is available, it'll consider that check successful and move on. So if your app takes 2 seconds to display that element, your tests will starts straight after!

If you want to make it less repetitive for all your tests, you can create a function to open a given page and wait for its content to be there before doing something else. Example:

// at the top of the test file
const openProfilePage = () => {
  cy.visit('profile');
  cy.get(
    '.profile',
    { timeout: 15000 }
  ).should('exist');
}

// in every tests after or in a before each
openProfilePage();

// test something else
like image 61
maxime1992 Avatar answered Sep 28 '22 05:09

maxime1992