-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
chore: Refactor cy.state('subject') and cy.then()
#22742
Changes from 9 commits
a3a9e35
d3aef86
5d81298
74fa0e5
916e6f1
7021ba8
834ccae
ac86823
485a3fa
45689b6
cf61e19
ec01d6d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ export default (Cypress, userOptions: Cypress.LogGroup.Config, fn: Cypress.LogGr | |
const endLogGroupCmd = $Command.create({ | ||
name: 'end-logGroup', | ||
injected: true, | ||
args: [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what's this change for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consistency. This homogenizes I've honestly forgotten exactly where it was throwing an error, but it was somewhere pretty arcane, and this one-line change meant I didn't have to add existence checks deep inside the command-queue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given this is an injected command, why do we need this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without this, we get errors in
I could add a guard against commands that don't have args in there, or I could ensure that every command has an args array and not need to guard against it. I prefer consistent object shapes over null checks when possible. The follow-up PR I'm currently working on removes the concept of 'injected' entirely (while maintaining all existing functionality and without editing any of the related tests). |
||
}) | ||
|
||
const forwardYieldedSubject = () => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,8 +15,8 @@ import type { ITimeouts } from '../cy/timeouts' | |
|
||
const debugErrors = Debug('cypress:driver:errors') | ||
|
||
const __stackReplacementMarker = (fn, ctx, args) => { | ||
return fn.apply(ctx, args) | ||
const __stackReplacementMarker = (fn, args) => { | ||
return fn(...args) | ||
} | ||
|
||
const commandRunningFailed = (Cypress, state, err) => { | ||
|
@@ -165,9 +165,11 @@ export class CommandQueue extends Queue<$Command> { | |
Cypress.once('command:enqueued', commandEnqueued) | ||
} | ||
|
||
args = [command.get('chainerId'), ...args] | ||
|
||
// run the command's fn with runnable's context | ||
try { | ||
ret = __stackReplacementMarker(command.get('fn'), this.state('ctx'), args) | ||
ret = __stackReplacementMarker(command.get('fn'), args) | ||
} catch (err) { | ||
throw err | ||
} finally { | ||
|
@@ -247,7 +249,7 @@ export class CommandQueue extends Queue<$Command> { | |
// we're finished with the current command so set it back to null | ||
this.state('current', null) | ||
|
||
this.state('subject', subject) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This PR removes https://github.com/search?q=cy.state%28%27subject%27%29&type=code What do you think about still setting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This PR changes the formatting of it, to be an object rather than a single entry, in preparation for changing it even further down the line (into an even more complex data structure). You're right though, if testing-library is relying on it, then this is a breaking change and I absolutely cannot make it as part of a Hm. This is really rough though. The call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, so thinking about this further, I think we can in fact leave That's what I mean when I say "mostly working" - I can add a shim to keep it working as-is (only a little bit broken). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So current plan:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated in latest commit. I now store the subject mapping in cy.state('subjects'), with cy.state('subject') being an alias (that logs a deprecation warning) for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch here. We should probably make a PR against testing-library once this lands, to save them the time/effort, and while this is fresh in our minds. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does PR likely needs to be flagged for release so a note can be made in the changelog that this usage has been deprecated if we are porting this functionality? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call. I've updated the PR description to note the change and the rational behind it. |
||
cy.setSubjectForChainer(command.get('chainerId'), subject) | ||
|
||
return subject | ||
}) | ||
|
@@ -278,7 +280,8 @@ export class CommandQueue extends Queue<$Command> { | |
}) | ||
|
||
this.state('index', index + 1) | ||
this.state('subject', command.get('subject')) | ||
|
||
cy.setSubjectForChainer(command.get('chainerId'), command.get('subject')) | ||
|
||
Cypress.action('cy:skipped:command:end', command) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain this? If I am understanding correctly, it seem like this would break the following?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the key is that cy.within works differently from cy.then - it never changes the subject. According to our docs (https://docs.cypress.io/api/commands/within#Yields):
So cy.within always matches the two conditions I mentioned in my other comment - the callback contains cypress commands, and we do not want to use their resolved subject as the new subject of the parent chainer. The existing automated tests back up this behavior.
I didn't know this about cy.within - I learned it by looking at the tests, being confused, then looking at the docs to see if the tests were correct. 🤣 I can't speak to why it works this way, just that it does and I'm trying to retain all the existing rules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah,
.within()
is a bit interesting in that regard -- but curious what these new rules are exactly? It seems this logic is maintaining parity with the current logic?Does your TODO comment mean you'd like to change this behavior later on or that you need to remove
cy.breakSubjectLinksToCurrentChainer()
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this logic is maintaining parity with existing functionality. The 'two rules' I mentioned are just guidelines to help understand when
breakSubjectLinksToCurrentChainer
is appropriate to use.The TODO comment is that I'll need to refactor
cy.within
as part of the effort of implementing selectors / fixing detached DOM. The goal will still be to maintain the existing functionality as part of any further work in here.