Skip to content

Commit 51ef99a

Browse files
authored
chore: reverting #22742 (#23047)
* Revert "chore: Refactor cy.state('subject') and `cy.then()` (#22742)" This reverts commit 0ed8dd5. * Run more tests
1 parent 4d3ad9e commit 51ef99a

File tree

19 files changed

+237
-221
lines changed

19 files changed

+237
-221
lines changed

circle.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ mainBuildFilters: &mainBuildFilters
2727
branches:
2828
only:
2929
- develop
30-
- tbiethman/electron-19
30+
- revert-22742
3131

3232
# usually we don't build Mac app - it takes a long time
3333
# but sometimes we want to really confirm we are doing the right thing
@@ -36,7 +36,7 @@ macWorkflowFilters: &darwin-workflow-filters
3636
when:
3737
or:
3838
- equal: [ develop, << pipeline.git.branch >> ]
39-
- equal: [ 'tbiethman/electron-19', << pipeline.git.branch >> ]
39+
- equal: [ 'revert-22742', << pipeline.git.branch >> ]
4040
- matches:
4141
pattern: "-release$"
4242
value: << pipeline.git.branch >>
@@ -45,7 +45,7 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
4545
when:
4646
or:
4747
- equal: [ develop, << pipeline.git.branch >> ]
48-
- equal: [ 'tbiethman/electron-19', << pipeline.git.branch >> ]
48+
- equal: [ 'revert-22742', << pipeline.git.branch >> ]
4949
- matches:
5050
pattern: "-release$"
5151
value: << pipeline.git.branch >>
@@ -129,7 +129,7 @@ commands:
129129
- run:
130130
name: Check current branch to persist artifacts
131131
command: |
132-
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "tbiethman/electron-19" ]]; then
132+
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "revert-22742" ]]; then
133133
echo "Not uploading artifacts or posting install comment for this branch."
134134
circleci-agent step halt
135135
fi
@@ -883,7 +883,7 @@ commands:
883883
fi
884884
885885
curl -L https://raw.githubusercontent.com/cypress-io/cypress/$branch/scripts/ensure-node.sh --output ci-ensure-node.sh
886-
else
886+
else
887887
# if no .node-version file exists, we no-op the node script and use the global yarn
888888
echo '' > ci-ensure-node.sh
889889
fi

packages/driver/cypress/e2e/commands/assertions.cy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ describe('src/cy/commands/assertions', () => {
806806
})
807807

808808
cy.get('body').then(() => {
809-
expect(cy.currentSubject()).to.match('body')
809+
expect(cy.state('subject')).to.match('body')
810810
})
811811
})
812812

packages/driver/cypress/e2e/commands/commands.cy.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ describe('src/cy/commands/commands', () => {
5858
cy
5959
.get('input:first')
6060
.parent()
61-
.command('login', '[email protected]')
62-
.then(($input) => {
61+
.command('login', '[email protected]').then(($input) => {
6362
expect($input.get(0)).to.eq(input.get(0))
6463
})
6564
})

packages/driver/cypress/e2e/commands/connectors.cy.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,16 +158,15 @@ describe('src/cy/commands/connectors', () => {
158158
})
159159
})
160160

161-
it('should pass the eventually resolved thenable value downstream', () => {
161+
it('should pass the eventual resolved thenable value downstream', () => {
162162
cy
163163
.wrap({ foo: 'bar' })
164164
.then((obj) => {
165165
return cy
166166
.wait(10)
167167
.then(() => {
168168
return obj.foo
169-
})
170-
.then((value) => {
169+
}).then((value) => {
171170
expect(value).to.eq('bar')
172171

173172
return value
@@ -310,7 +309,7 @@ describe('src/cy/commands/connectors', () => {
310309
return $div
311310
})
312311
.then(function () {
313-
expect(cy.currentSubject()).not.to.be.instanceof(this.remoteWindow.$)
312+
expect(cy.state('subject')).not.to.be.instanceof(this.remoteWindow.$)
314313
})
315314
})
316315
})
@@ -424,6 +423,7 @@ describe('src/cy/commands/connectors', () => {
424423

425424
cy.get('div:first').invoke('parent').then(function ($parent) {
426425
expect($parent).to.be.instanceof(this.remoteWindow.$)
426+
expect(cy.state('subject')).to.match(parent)
427427
})
428428
})
429429
})

packages/driver/cypress/e2e/cypress/cy.cy.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -133,16 +133,6 @@ describe('driver/src/cypress/cy', () => {
133133
expect(userInvocationStack).to.include('.cy.js')
134134
})
135135
})
136-
137-
it('supports cy.state(\'subject\') for backwards compatability', () => {
138-
cy.stub(Cypress.utils, 'warning')
139-
const a = {}
140-
141-
cy.wrap(a).then(() => {
142-
expect(cy.state('subject')).to.equal(a)
143-
expect(Cypress.utils.warning).to.be.calledWith('`cy.state(\'subject\')` has been deprecated and will be removed in a future release. Consider migrating to `cy.currentSubject()` instead.')
144-
})
145-
})
146136
})
147137

148138
context('custom commands', () => {

packages/driver/src/cross-origin/origin_fn.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const handleOriginFn = (Cypress: Cypress.Cypress, cy: $Cy) => {
105105
queueFinished = true
106106
setRunnableStateToPassed()
107107
Cypress.specBridgeCommunicator.toPrimary('queue:finished', {
108-
subject: cy.currentSubject(),
108+
subject: cy.state('subject'),
109109
}, {
110110
syncGlobals: true,
111111
})

packages/driver/src/cy/commands/connectors.ts

Lines changed: 80 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,47 @@ export default function (Commands, Cypress, cy, state) {
100100

101101
cy.once('command:enqueued', enqueuedCommand)
102102

103+
// this code helps juggle subjects forward
104+
// the same way that promises work
105+
const current = state('current')
106+
const next = current.get('next')
107+
108+
// TODO: this code may no longer be necessary
109+
// if the next command is chained to us then when it eventually
110+
// runs we need to reset the subject to be the return value of the
111+
// previous command so the subject is continuously juggled forward
112+
if (next && next.get('chainerId') === current.get('chainerId')) {
113+
const checkSubject = (newSubject, args) => {
114+
if (state('current') !== next) {
115+
return
116+
}
117+
118+
// get whatever the previous commands return
119+
// value is. this likely does not match the 'var current'
120+
// command in the case of nested cy commands
121+
const s = next.get('prev').get('subject')
122+
123+
// find the new subject and splice it out
124+
// with our existing subject
125+
const index = _.indexOf(args, newSubject)
126+
127+
if (index > -1) {
128+
args.splice(index, 1, s)
129+
}
130+
131+
return cy.removeListener('next:subject:prepared', checkSubject)
132+
}
133+
134+
cy.on('next:subject:prepared', checkSubject)
135+
}
136+
103137
const getRet = () => {
104138
let ret = fn.apply(ctx, args)
105139

140+
if (cy.isCy(ret)) {
141+
ret = undefined
142+
}
143+
106144
if (ret && invokedCyCommand && !ret.then) {
107145
$errUtils.throwErrByPath('then.callback_mixes_sync_and_async', {
108146
onFail: options._log,
@@ -123,11 +161,6 @@ export default function (Commands, Cypress, cy, state) {
123161
return subject
124162
}
125163

126-
// If the user callback returned a non-null value, we break cypress' subject chaining
127-
// logic, so that we can use this subject as-is rather than the subject generated by
128-
// any chainers inside the callback (if any exist).
129-
cy.breakSubjectLinksToCurrentChainer()
130-
131164
return ret
132165
}).catch(Promise.TimeoutError, () => {
133166
return $errUtils.throwErrByPath('invoke_its.timed_out', {
@@ -465,16 +498,54 @@ export default function (Commands, Cypress, cy, state) {
465498
$errUtils.throwErrByPath('each.invalid_argument')
466499
}
467500

468-
if (subject?.length === undefined) {
501+
const nonArray = () => {
469502
return $errUtils.throwErrByPath('each.non_array', {
470503
args: { subject: $utils.stringify(subject) },
471504
})
472505
}
473506

507+
try {
508+
if (!('length' in subject)) {
509+
nonArray()
510+
}
511+
} catch (e) {
512+
nonArray()
513+
}
514+
474515
if (subject.length === 0) {
475516
return subject
476517
}
477518

519+
// if we have a next command then we need to
520+
// slice in this existing subject as its subject
521+
// due to the way we queue promises
522+
const next = state('current').get('next')
523+
524+
if (next) {
525+
const checkSubject = (newSubject, args, firstCall) => {
526+
if (state('current') !== next) {
527+
return
528+
}
529+
530+
// https://github.com/cypress-io/cypress/issues/4921
531+
// When dual commands like contains() is used as the firstCall (cy.contains() style),
532+
// we should not prepend subject.
533+
if (!firstCall) {
534+
// find the new subject and splice it out
535+
// with our existing subject
536+
const index = _.indexOf(args, newSubject)
537+
538+
if (index > -1) {
539+
args.splice(index, 1, subject)
540+
}
541+
}
542+
543+
return cy.removeListener('next:subject:prepared', checkSubject)
544+
}
545+
546+
cy.on('next:subject:prepared', checkSubject)
547+
}
548+
478549
let endEarly = false
479550

480551
const yieldItem = (el, index) => {
@@ -502,16 +573,11 @@ export default function (Commands, Cypress, cy, state) {
502573

503574
// generate a real array since bluebird is finicky and
504575
// doesnt want an 'array-like' structure like jquery instances
576+
// need to take into account regular arrays here by first checking
577+
// if its an array instance
505578
return Promise
506579
.each(_.toArray(subject), yieldItem)
507-
.then(() => {
508-
// cy.each does *not* want to use any subjects that the user's callback generated - therefore we break
509-
// cypress' subject chaining logic, which by default would override this with any subjects generated by
510-
// the callback function.
511-
cy.breakSubjectLinksToCurrentChainer()
512-
513-
return subject
514-
})
580+
.return(subject)
515581
},
516582
})
517583

packages/driver/src/cy/commands/misc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default (Commands, Cypress, cy, state) => {
3232
const restoreCmdIndex = state('index') + 1
3333

3434
cy.queue.insert(restoreCmdIndex, $Command.create({
35-
args: [cy.currentSubject()],
35+
args: [state('subject')],
3636
name: 'log-restore',
3737
fn: (subject) => subject,
3838
}))

packages/driver/src/cy/commands/querying/within.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ export default (Commands, Cypress, cy, state) => {
3535

3636
fn.call(cy.state('ctx'), subject)
3737

38-
const cleanup = () => {
39-
cy.removeListener('command:start', setWithinSubject)
40-
}
38+
const cleanup = () => cy.removeListener('command:start', setWithinSubject)
4139

4240
// we need a mechanism to know when we should remove
4341
// our withinSubject so we dont accidentally keep it
@@ -78,10 +76,6 @@ export default (Commands, Cypress, cy, state) => {
7876
})
7977
}
8078

81-
// TODO: Rework cy.within to use chainer-based subject chaining, rather than its custom withinSubject state.
82-
// For now, we leave this logic in place and just ensure that the new rules don't interfere with it.
83-
cy.breakSubjectLinksToCurrentChainer()
84-
8579
return subject
8680
}
8781

packages/driver/src/cy/logGroup.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ export default (Cypress, userOptions: Cypress.LogGroup.Config, fn: Cypress.LogGr
2727
const endLogGroupCmd = $Command.create({
2828
name: 'end-logGroup',
2929
injected: true,
30-
args: [],
3130
})
3231

3332
const forwardYieldedSubject = () => {

0 commit comments

Comments
 (0)