Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular component tests don't correctly handle time with cy.clock() #27602

Closed
halbekanne opened this issue Aug 19, 2023 · 7 comments
Closed

Angular component tests don't correctly handle time with cy.clock() #27602

halbekanne opened this issue Aug 19, 2023 · 7 comments
Labels
CT Issue related to component testing stale no activity on this issue for a long period

Comments

@halbekanne
Copy link

halbekanne commented Aug 19, 2023

Current behavior

Consider the following scenario. My Angular component:

  1. Fetches data from a server, in the example "Apple"
  2. Displays that data
  3. Fetches the data again after 1 second (using rxjs interval(1000)) and getting new data, in the example "Banana"
  4. Displays the new data (and so on)

Now in the component test I mocked calls to the backend that return something different after each call to test that the webpage gets updated with new data if its available on the server. It is a similar testing setup as it has been described in this blog post from Cypress.

As suggested in the blog post, I did this using cy.clock()and cy.tick(1000) in order to control and pass time.

When I run this test with Chrome, it doesn't update the component with the new data and I get the following error: "AssertionError: Timed out retrying after 4000ms: Expected to find content: 'Banana' within the element: <div.container> but never did."

In the example repository below, the Angular component uses RxJS interval() in order to fetch repeatedly, but other methods of setting up a timed fetch like window.setInterval() also doesn't seem to work.

Desired behavior

The test should run successfully using cy.clock() and cy.tick() using the mocked data and the Angular component should update with the new data.

Test code to reproduce

Example Angular Component:

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, HttpClientModule],
  providers: [],
  template: `
    <div class="container">
        {{ text }}
    </div>
  `,
  styles: [],
})
export class AppComponent implements OnInit {
  text = 'Loading...';
  httpClient = inject(HttpClient);

  ngOnInit() {
    interval(1000).pipe(
      startWith(-1),
      switchMap(() => {
        return this.httpClient.get<any>('https://yesno.wtf/api');
      })
    ).subscribe((res) => {
      this.text = res.answer;
    });
  }
}

Example Component Test:

describe('App', () => {
  it('displays data from the server twice', () => {
    cy.clock();

    cy.intercept('GET', 'https://yesno.wtf/api', {
      body: {
        answer: 'Apple',
      }
    }).as('apple');
    cy.mount(AppComponent);
    cy.get('.container').contains('Apple');

    cy.intercept('GET', 'https://yesno.wtf/api', {
      body: {
        answer: 'Banana',
      }
    }).as('banana');
    cy.tick(1000);
    cy.get('.container').contains('Banana');
  });
});

Example Repo with both files: https://github.com/halbekanne/cy-ng-intercept-rxjs-minimal-example

Cypress Version

12.17.2

Node version

v18.12.1

Operating System

macOS 13.3.1

Debug Logs

No response

Other

No response

@halbekanne halbekanne changed the title Angular component test don't correctly handle cy.clock() Angular component tests don't correctly handle cy.clock() Aug 19, 2023
@halbekanne halbekanne changed the title Angular component tests don't correctly handle cy.clock() Angular component tests don't correctly handle time with cy.clock() Aug 19, 2023
@tomalaforge
Copy link

@halbekanne did you find a way to solve your issue. I'm running into the same issue with cypress fake timers and rxjs interval.

@halbekanne
Copy link
Author

halbekanne commented Oct 18, 2023

@tomalaforge sadly that's not the case. I found a rather tedious workaround: create an abstraction layer for timers (I created a timer service), use it to replace the real timer with a fake one (e.g. a subject that you can call "next()" on), then find a way to call this fake timer from the Cypress test (e.g. define a function in the global window object that calls the next() function). That's the best I could come up with.

I'm pretty sure it's not meant to work like that and that there should be an actual solution, because working with timers or intervals in Angular is not an uncommon scenario.

@tomalaforge
Copy link

Thanks for your answer. But for sure, that's not the best solution, but the temporary workaround 👍

@mpavel
Copy link

mpavel commented Oct 19, 2023

@halbekanne , we also had issues with the cy.clock() in a large React application, and I've explained here how we overcame this: #27744.

For us, in order to re-render the UI, we had to:

  • restore the clock with cy.clock().invoke('restore');
  • or do a cy.tick(100) and cy.wait(100) together, one after another (just not sure now in which order exactly)

Maybe the same thing will work in Angular also, if you restore the clock before making the UI assertions 🤔

@tehshin
Copy link

tehshin commented Dec 5, 2023

@mpavel tried both workarounds and none worked in case of Angular Component Tests. 🤷

@jennifer-shehane jennifer-shehane added CT Issue related to component testing and removed stage: routed to ct labels Dec 15, 2023
@cypress-app-bot
Copy link
Collaborator

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

@cypress-app-bot cypress-app-bot added the stale no activity on this issue for a long period label Jun 12, 2024
@cypress-app-bot
Copy link
Collaborator

This issue has been closed due to inactivity.

@cypress-app-bot cypress-app-bot closed this as not planned Won't fix, can't repro, duplicate, stale Jun 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CT Issue related to component testing stale no activity on this issue for a long period
Projects
None yet
Development

No branches or pull requests

6 participants