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

Alias seems to not store it's value #25173

Closed
jmiechowicz opened this issue Dec 15, 2022 · 18 comments · Fixed by #25251
Closed

Alias seems to not store it's value #25173

jmiechowicz opened this issue Dec 15, 2022 · 18 comments · Fixed by #25251
Assignees

Comments

@jmiechowicz
Copy link

jmiechowicz commented Dec 15, 2022

Current behavior

During the test I'm comparing two values

First one is stored as 'backgroundImageDefault' with following code

    cy.get(selectors.pageAddress)
      .prev()
      .invoke('css', 'backgroundImage')
      .as('backgroundImageDefault');

At this point the backgroundImageDefault has value https://host.com/smth/defaultImage.jpg.

Then I'm changing the image, the new image obviously has a new address, https://host.com/smth/changedImage.jpg.

    cy.get('@backgroundImageDefault').then((background) => {
      cy.get(selectors.pageAddress)
        .prev()
        .should('not.have.css', 'background-image', background);
    });

It fails becouse when comparing it seems that alias 'backgroundImageDefault' now has value of https://host.com/smth/changedImage.jpg instead of it's assigned value of https://host.com/smth/defaultImage.jpg.

Desired behavior

Until I upgraded to 12.0.0/12.1.0 the test simply passed and the value stored in the backgroundImageDefault was correct.

Test code to reproduce

It's the code mentioned in current behaviour

Cypress Version

12.1.0

Node version

v16.15.1

Operating System

macOS 13.1

Debug Logs

No response

Other

No response

@kpratik0912
Copy link

Facing same issue after updating to v12.1.0

@ArturMiszkowicz
Copy link

I am also facing this issue in v12.1.0

@Deop
Copy link

Deop commented Dec 16, 2022

Not sure if it's the same issue, but starting v12.0 following code doesn't work.
cy.get('button').as('button').should('not.exist);
It fails with Expected to find element: button, but never found it. But in 11.2.0 it worked.

@vadymbutlerovskyi
Copy link

vadymbutlerovskyi commented Dec 16, 2022

Facing the same issue but in different context. I believe there is a bug or my misunderstanding of the new behavior of alias feature. I made an upgrade from version 10.6.0 to 12.1.0 and now cannot make some case work. Our app has tabs in its UI interface, like in browser but built-in UI, clicking on which, modifies the end of URL. E.g.: going from Tab1 {domain}/{tab1id} to Tab2 would result in URL being: {domain}/{tab2id}.
Imagine I switched to Tab2 and want to keep URL as alias tab2Selected, so I put setting it in the before clause of the test. Then in the test body, I will call this URL after switching to Tab1, via:

NavigationBar.switchToTab(1);
Tabs.byTitle('Tab 1').isActive(true);

cy.get(`@tab2Selected`).then((url) => {
      cy.visit(url);
      Tabs.byTitle('Tab 2').isActive(true);
 });

Therefore, when opening URL from tab2Selected, I should be calling {domain}/{tab2id} because I saved it when I was in Tab2 and this was true according to logs, however, the alias tab2Selected will be overwritten to {domain}/{tab1id}. According to my investigations, this is because I made a switch to Tab1 and this overwritten the alias tab2Selected, but it has no intense of it, it's just a click. Hence when opening this URL I will end up in Tab1. I made the same operation while stopping the test for 10 second and manually switching to Tab1, Cypress again overwritten the alias forgetting it did set it while being Tab2. Moreover, I also executed switches between tabs multiple times with Cypress and via logging the content of tab2Selected alias I managed to confirm that the alias was updated every time I switch to the new tab and URL is being updated. I believe this is false behavior because alias should stay as is until it is intentionally changed. From the logs screenshot, you can see that the URL of alias being changed from /RNWxrlmh to /vhwC5p0f and back as long as I switch between tabs
image

@BlueWinds
Copy link
Contributor

It fails becouse when comparing it seems that alias 'backgroundImageDefault' now has value of https://host.com/smth/changedImage.jpg instead of it's assigned value of https://host.com/smth/defaultImage.jpg.

Desired behavior

Until I upgraded to 12.0.0/12.1.0 the test simply passed and the value stored in the backgroundImageDefault was correct.

This was an intentional change in the behavior of aliases - basically we hadn't realized people were relying on the old behavior, and thought that accurately reflecting the current state of the application was always desired.

Currently discussing with the rest of the team and trying to figure out a good solution here, but as a temporary workaround, you can add a non-query command to 'break' the subject chain. Eg:

    cy.get(selectors.pageAddress)
      .prev()
      .invoke('css', 'backgroundImage')
      .then(() => {}) // Add this in
      .as('backgroundImageDefault');

.then() breaks the subject chain - you'll just be aliasing the value, not the full query of .get().prev().invoke()

Just to reiterate, this is just a workaround you can use - we're still figuring out what to do here. :)

@edikdeisling
Copy link
Contributor

edikdeisling commented Dec 19, 2022

@BlueWinds Am I right that if we need stored value it's better to use aliases this way?(with this)

cy.get(selectors.pageAddress)
      .prev()
      .invoke('css', 'backgroundImage')
      .as('backgroundImageDefault');

cy.then(function() {
      cy.get(selectors.pageAddress)
        .prev()
        .should('not.have.css', 'background-image', this.backgroundImageDefault);
});

@BlueWinds
Copy link
Contributor

A couple of options we're considering:

A. .as('username', {type: 'query|value'}) - So you'd choose, when storing an alias, if you want a live-updating value or a static one.

B. .asValue('username') - Or we could add a new command - .as() would store a 'live' alias, and .asValue() would store a static value.

C. cy.get('@username', {aliasType: 'value|query'}) - Or add an option to .get(), to determine if you want the 'live' result of an alias, or the one that existed when you saved it.

D. cy.unwrap('@username') - Or add an entirely new command, where .as() reruns queries and .unwrap() uses the one that existed when you created the alias.

Anyone have strong feelings about any of these? I'm leaning towards A.

@samtsai
Copy link
Contributor

samtsai commented Dec 20, 2022

I like A, would we probably default to { type: 'query' } and document that this is how it was always meant to work? I mean it's a little more work for people depending on the value but speaking for my team, we can manage to be explicit in our tests that need a different default.

I think C would be confusing to change it on the get at least in my mind we focus more on when we store values, like if we wanted to do a .as("originalValue") and then later compare to a new value, sample usage:

cy.get("@originalUrl").then(url => {
    cy.url().as("newUrl").should("not.equal", url)
})

@ArturMiszkowicz
Copy link

I like A and B :)

B is more explicit but A gives no work if someone is not using aliases to store values

@edikdeisling
Copy link
Contributor

A and B look nice.
From my perspective default value should be value rather than query. Because only value works consistently in cases .invoke(...).as() and .then(...).as()(query won't requery .then) . Also storing intermediate values in tests can only be done with aliases. If it's needed to write more code here it means that storing intermediate values in Cypress becomes more painful.
But if query should stay default - B looks less painful for just storing values.

@jmiechowicz
Copy link
Author

I also believe that both A and B would be great to use. However I'm a bigger fan of B due to being way more explicit.

@Deop
Copy link

Deop commented Dec 21, 2022

I'm as well for options A and B. B provides good way to differentiate the two ways of handling aliases. However, if we go with A I think the default value should be the one that was before 12.0 update to not break existing code for people, forcing them to update/refactor their code.

@BlueWinds, could you please tell if those changes would bring back functionality like this to work again? cy.get('button').as('button').should('not.exist); It used to properly assert that such elements do not exist, not it fails with no element found.

@BlueWinds
Copy link
Contributor

@BlueWinds, could you please tell if those changes would bring back functionality like this to work again? cy.get('button').as('button').should('not.exist); It used to properly assert that such elements do not exist, not it fails with no element found.

That sounds like a different and unrelated issue; please open a new ticket with a reproduction so we can look at that separately.

@verheyenkoen
Copy link
Contributor

@BlueWinds Am I right that if we need stored value it's better to use aliases this way?(with this)

I wouldn't say using cy.then(function() { return this.theAliasKey; }) is "better". It's just another way to retrieve the alias value and in this case it's probably the only workaround until this bug is fixed.

@verheyenkoen
Copy link
Contributor

If anyone is interested, I created a repo with some tests to show what still works and what is broken: https://github.com/verheyenkoen/cypress-primitive-alias-bug/blob/main/cypress/e2e/test.cy.js

@jonasSel
Copy link

jonasSel commented Jan 13, 2023

Can't believe that the use case (save value for later, while changed in between) has been ignored during development of 12+. It is a central piece in my cypress code.

@filipedanunes
Copy link

Just keep everything as it was before the bug, values should be the default please.

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Jan 24, 2023

Released in 12.4.0.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v12.4.0, please open a new issue.

@cypress-bot cypress-bot bot removed the stage: needs review The PR code is done & tested, needs review label Jan 24, 2023
@cypress-bot cypress-bot bot locked as resolved and limited conversation to collaborators Jan 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.