16

How do you programmatically interact with Angular/NGRX from Cypress? The cypress docs seem to refer only to React: https://www.cypress.io/blog/2018/11/14/testing-redux-store/

// expose store when run in Cypress
if (window.Cypress) {
  window.store = store
}
cy
 .window()
 .its('store')
 .invoke('dispatch', { type: 'ADD_TODO', text: 'Test dispatch' })
// check if the app has updated its UI

This would be the React approach; so what about Angular?

indigo
  • 1,067
  • 4
  • 15
  • 26
Phil
  • 7,065
  • 8
  • 49
  • 91
  • cypress is made to simulate a user behavior. Why would you want to interact with the store directly? It's to build e2e tests so if you need to mock data, mock them at the HTTP level using cy.server and cy.route – maxime1992 Jan 22 '20 at 14:10
  • 1
    @maxime1992 see the linked blog article. This question is definitely debatable. I have discussed it with other developers on meetups and the majority would agree with you (not the main dev of cypress though, see blog). But IMHO as long as you can guarantee (!!!) getting to one certain app state by UI, you could set it up programatically to be used as a starting point for other tests. The benefit would be speed. The downsides would be misusing e2e tests for unit-testing and obfuscation for non-developers checking out the test-execution in the browser. – Phil Jan 22 '20 at 14:50
  • my problem is that I want take the state indicator from store to indicate that all stats are loaded and indicate that I can run cypress test. Other wise I got race condition and cypress runs before my page are fully loaded.. but I can't get state from ngrx store directly in cypress – Huantao Jun 24 '20 at 02:37

2 Answers2

12

In Angular it is almost the same. In your AppComponent or wherever you have the store you can do something like:

// Expose the store
@Component({...})
export class AppComponent {
    constructor(private store: Store<AppState>){
        if(window.Cypress){
            window.store = this.store;
        }
    }
}

You can then create your own Cypress utility:

function dispatchAction(action: Action): Cypress.Chainable<any> {
    return cy.window().then(w => {
        const store = w.store;
        store.dispatch(action);
    });
}

And finally you can use it in a Cypress test:

dispatchAction(new MyAction()).then(() => {
     // Assert the side effect of your action
     // ...
     // cy.get('.name').should('exist');
});
Nicola Tommasi
  • 547
  • 6
  • 10
0

You can access State like this (works in addition to the already accepted answer):

import { firstValueFrom } from 'rxjs';

 

 cy.window().its('store').then((store: any) => {
   firstValueFrom(store.source).then((state) => {
     cy.log('got state', state);
   });
 });