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

Component tests fail when angular-query is used in the component #30327

Open
ekrapfl opened this issue Sep 30, 2024 · 12 comments
Open

Component tests fail when angular-query is used in the component #30327

ekrapfl opened this issue Sep 30, 2024 · 12 comments
Labels
CT Issue related to component testing stage: needs investigating Someone from Cypress needs to look at this

Comments

@ekrapfl
Copy link

ekrapfl commented Sep 30, 2024

Current behavior

We are using Angular Query (TanStack Query's Angular port) in our project, and we have noticed that it can interfere with our Cypress component tests in some cases. To illustrate this, we have made a simple modification to the Cypress component testing sample app for standalone Angular. If you pull it down and run the test-component spec, you will see that none of the tests pass. It appears as though change detection is not running properly once the TanStack Query (TSQ) is injected in the component file. To see the tests work again, comment out the query property in test-component.component.ts.

Reproduction fork

image

Notes:

  • There does not appear to be any issue when running the app, only when running through Cypress component tests.
  • I have tested this in an ultra-simple repo with nothing but a simple component and a Cypress component test as well (if you would prefer this format): simple repro
  • This bug has been cross-posted to TanStack Query as well.

Desired behavior

I would expect that injecting a simple TSQ would not affect change detection in Cypress component tests.

Test code to reproduce

cypress-component-testing-apps Reproduction fork

  • Run the tests for angular-standalone -> test-component

Simple Angular Repro

  • npm ci
  • npx cypress open
  • Run component tests

Cypress Version

13.15

Node version

20.11.0

Operating System

MacOS 15.0

Debug Logs

No response

Other

No response

@jennifer-shehane jennifer-shehane added CT Issue related to component testing stage: needs investigating Someone from Cypress needs to look at this labels Oct 1, 2024
@abdelsalamshahlol
Copy link

abdelsalamshahlol commented Oct 3, 2024

I've encountered the same issues on my test project, leading to your report.
However, I got all assertions to pass from your sample by firing change detection manually and using then(()=>...

  cy.mount(FailComponent, {
      providers: [provideAngularQuery(new QueryClient())],
    }).then(({fixture})=>{
       fixture.detectChanges()

      cy.get('.first').should('have.class', 'selected');

      cy.get('.second').click().then(()=>{
        fixture.detectChanges()
        cy.get('.second').should('have.class', 'selected');
      });


      cy.get('.third').click().then(()=>{
        fixture.detectChanges()
        cy.get('.third').should('have.class', 'selected');
      });

I know this doesn't solve the issue but it may help with the investigations.

@ekrapfl
Copy link
Author

ekrapfl commented Oct 3, 2024

Yep, that is totally true. If I strategically fire change detection manually all over the place in my tests, it will work. It's like something has broken something with change detection itself, though, and it doesn't happen automatically anymore.

@ekrapfl
Copy link
Author

ekrapfl commented Nov 12, 2024

Just curious, is the Cypress team looking into this at all?

@jennifer-shehane
Copy link
Member

@ekrapfl We're not currently looking into this problem at the moment. Our project board is generally up to date on what we're working on: https://github.com/orgs/cypress-io/projects/13

@ekrapfl
Copy link
Author

ekrapfl commented Nov 13, 2024

Thanks for the update, @jennifer-shehane. Is there any way to get that bumped up in priority at all? My company is a paying customer. Is there a support channel I should go through instead?

@ekrapfl
Copy link
Author

ekrapfl commented Nov 13, 2024

I would be very interested in anyone's thoughts on a workaround for this as well. I have tried sprinkling tons of manual change detection checks into the tests, but nothing seems to jar it loose completely.

@mschile
Copy link
Contributor

mschile commented Nov 14, 2024

Not necessarily a workaround, but instead of sprinkling change detection checks everywhere in your tests, Cypress does allow you to overwrite built-in commands, so you could do something like:

Cypress.Commands.overwrite('should', function (originalFn, ...args) {
  cy.window().its('cdr').invoke('detectChanges').then(() => {
    return originalFn.apply(this, args)
  })
})

Now, whenever you do .should(...) in a test, it will first run detectChanges.

@AtofStryker
Copy link
Contributor

AtofStryker commented Nov 15, 2024

I took a look into this recently, and for whatever reason, whenStable is never achieved when tanstack queries are used in the component, which means autoDetectChanges is never called inside Cypress. I'm hesitant to remove the line currently because I am not fully aware of the consequences, but you could try to either:

  • patch @cypress/angular-signals to comment out that line
  • wrap the mount function to have a thenable that sets autoDetectChanges on the fixture, like this:
// ./cypress/support/component.ts
import { mount } from 'cypress/angular-signals'

// Augment the Cypress namespace to include type definitions for
// your custom command.
// Alternatively, can be defined in cypress/support/component.d.ts
// with a <reference path="./component" /> at the top of your spec.
declare global {
  namespace Cypress {
    interface Chainable {
      mount: typeof mount
    }
  }
}

Cypress.Commands.add('mount', function (...args) {
  mount(...args).then(({ fixture }) => {
    fixture.autoDetectChanges(true)
  })
})

@ekrapfl would you mind trying this work around? I am able to get all tests to pass in the test-component.component.cy.ts with this change. I created a PR against your fork to try cg-roling/cypress-component-testing-apps#1

@ekrapfl
Copy link
Author

ekrapfl commented Nov 15, 2024

Wow, great call! That does seem to work to fix all of the tests I had failing for this reason, but it also breaks some others that were previously working. I am thinking that I might be able to work around it for now by doing something like:

cy.mount(MyComponent).then(({ fixture }) => fixture.autoDetectChanges(true));

And I would only do that for the problematic components. Not ideal, but neither is the whole situation. Does that seem like potentially a good workaround for the moment?

@mschile
Copy link
Contributor

mschile commented Nov 18, 2024

@ekrapfl, yes, that seems like a good workaround. You would also try setting up a mount command that accepts a parameter to autoDetectChangesAfterMount.

@ekrapfl
Copy link
Author

ekrapfl commented Nov 18, 2024

An interesting note for the Cypress mount command. I agree that there is some issue with whenStable while using TanStack Query. I was finding some similar oddities with Jasmine unit tests while using TanStack Query. But I found a very simple workaround in Jasmine tests: make sure to run compileComponents on the TestBed. Once I did that, whenStable seemed to work properly, as did any other quirks I was seeing. Normally, that shouldn't be necessary when running via ng test according to the docs, but in my case, that definitely fixed the issue.

I was curious if I could apply that change to the Cypress mount command and globally have it compileComponents, but I struggled to get that plugged in properly. Is that something Cypress would want to investigate to see if it fixes this kind of issue? Calling .compileComponents on the TestBed during mount, that is?

@AtofStryker
Copy link
Contributor

I was curious if I could apply that change to the Cypress mount command and globally have it compileComponents, but I struggled to get that plugged in properly. Is that something Cypress would want to investigate to see if it fixes this kind of issue? Calling .compileComponents on the TestBed during mount, that is?

I don't see why we couldn't. It looks to be harmless according to the Angular docs, and we could just add the call in initTestBed. The only weirdness would be that the call my be async, which would make the mount function async. Either way, its likely worth looking into.

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 stage: needs investigating Someone from Cypress needs to look at this
Projects
None yet
Development

No branches or pull requests

5 participants