mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-21 06:30:49 -06:00
feat: update .within to use internal log group api (#20980)
This commit is contained in:
@@ -48,6 +48,23 @@ describe('src/cy/commands/querying/within', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('can be chained off an alias', () => {
|
||||
const form = cy.$$('#by-name')
|
||||
|
||||
cy.get('#by-name').as('nameForm')
|
||||
.within(() => {})
|
||||
.then(($form) => {
|
||||
expect($form.get(0)).to.eq(form.get(0))
|
||||
})
|
||||
|
||||
cy.get('#by-name').as('nameForm')
|
||||
.within(() => {
|
||||
cy.get('input').should('be.visible')
|
||||
})
|
||||
|
||||
cy.get('@nameForm').should('be.visible')
|
||||
})
|
||||
|
||||
it('can call child commands after within on the same subject', () => {
|
||||
const input = cy.$$('#by-name input:first')
|
||||
|
||||
@@ -199,6 +216,20 @@ describe('src/cy/commands/querying/within', () => {
|
||||
expect(lastLog.get('snapshots')[0]).to.be.an('object')
|
||||
})
|
||||
})
|
||||
|
||||
it('provides additional information in console prop', () => {
|
||||
cy.get('div').within(() => {})
|
||||
.then(function () {
|
||||
const { lastLog } = this
|
||||
|
||||
const consoleProps = lastLog.get('consoleProps')()
|
||||
|
||||
expect(consoleProps).to.be.an('object')
|
||||
expect(consoleProps.Command).to.eq('within')
|
||||
expect(consoleProps.Yielded).to.not.be.null
|
||||
expect(consoleProps.Yielded).to.have.length(55)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('errors', {
|
||||
|
||||
@@ -2,12 +2,86 @@ import _ from 'lodash'
|
||||
|
||||
import { $Command } from '../../../cypress/command'
|
||||
import $errUtils from '../../../cypress/error_utils'
|
||||
import group from '../../logGroup'
|
||||
|
||||
export default (Commands, Cypress, cy, state) => {
|
||||
const withinFn = (subject, fn) => {
|
||||
// reference the next command after this
|
||||
// within. when that command runs we'll
|
||||
// know to remove withinSubject
|
||||
const next = state('current').get('next')
|
||||
|
||||
// backup the current withinSubject
|
||||
// this prevents a bug where we null out
|
||||
// withinSubject when there are nested .withins()
|
||||
// we want the inner within to restore the outer
|
||||
// once its done
|
||||
const prevWithinSubject = state('withinSubject')
|
||||
|
||||
state('withinSubject', subject)
|
||||
|
||||
// https://github.com/cypress-io/cypress/pull/8699
|
||||
// An internal command is inserted to create a divider between
|
||||
// commands inside within() callback and commands chained to it.
|
||||
const restoreCmdIndex = state('index') + 1
|
||||
|
||||
cy.queue.insert(restoreCmdIndex, $Command.create({
|
||||
args: [subject],
|
||||
name: 'within-restore',
|
||||
fn: (subject) => subject,
|
||||
}))
|
||||
|
||||
state('index', restoreCmdIndex)
|
||||
|
||||
fn.call(cy.state('ctx'), subject)
|
||||
|
||||
const cleanup = () => cy.removeListener('command:start', setWithinSubject)
|
||||
|
||||
// we need a mechanism to know when we should remove
|
||||
// our withinSubject so we dont accidentally keep it
|
||||
// around after the within callback is done executing
|
||||
// so when each command starts, check to see if this
|
||||
// is the command which references our 'next' and
|
||||
// if so, remove the within subject
|
||||
const setWithinSubject = (obj) => {
|
||||
if (obj !== next) {
|
||||
return
|
||||
}
|
||||
|
||||
// okay so what we're doing here is creating a property
|
||||
// which stores the 'next' command which will reset the
|
||||
// withinSubject. If two 'within' commands reference the
|
||||
// exact same 'next' command, then this prevents accidentally
|
||||
// resetting withinSubject more than once. If they point
|
||||
// to different 'next's then its okay
|
||||
if (next !== state('nextWithinSubject')) {
|
||||
state('withinSubject', prevWithinSubject || null)
|
||||
state('nextWithinSubject', next)
|
||||
}
|
||||
|
||||
// regardless nuke this listeners
|
||||
cleanup()
|
||||
}
|
||||
|
||||
// if next is defined then we know we'll eventually
|
||||
// unbind these listeners
|
||||
if (next) {
|
||||
cy.on('command:start', setWithinSubject)
|
||||
} else {
|
||||
// remove our listener if we happen to reach the end
|
||||
// event which will finalize cleanup if there was no next obj
|
||||
cy.once('command:queue:before:end', () => {
|
||||
cleanup()
|
||||
state('withinSubject', null)
|
||||
})
|
||||
}
|
||||
|
||||
return subject
|
||||
}
|
||||
|
||||
Commands.addAll({ prevSubject: ['element', 'document'] }, {
|
||||
within (subject, options, fn) {
|
||||
let userOptions = options
|
||||
const ctx = this
|
||||
|
||||
if (_.isUndefined(fn)) {
|
||||
fn = userOptions
|
||||
@@ -16,90 +90,20 @@ export default (Commands, Cypress, cy, state) => {
|
||||
|
||||
options = _.defaults({}, userOptions, { log: true })
|
||||
|
||||
if (options.log) {
|
||||
options._log = Cypress.log({
|
||||
$el: subject,
|
||||
message: '',
|
||||
timeout: options.timeout,
|
||||
})
|
||||
const groupOptions: Cypress.LogGroup.Config = {
|
||||
log: options.log,
|
||||
$el: subject,
|
||||
message: '',
|
||||
timeout: options.timeout,
|
||||
}
|
||||
|
||||
if (!_.isFunction(fn)) {
|
||||
$errUtils.throwErrByPath('within.invalid_argument', { onFail: options._log })
|
||||
}
|
||||
|
||||
// reference the next command after this
|
||||
// within. when that command runs we'll
|
||||
// know to remove withinSubject
|
||||
const next = state('current').get('next')
|
||||
|
||||
// backup the current withinSubject
|
||||
// this prevents a bug where we null out
|
||||
// withinSubject when there are nested .withins()
|
||||
// we want the inner within to restore the outer
|
||||
// once its done
|
||||
const prevWithinSubject = state('withinSubject')
|
||||
|
||||
state('withinSubject', subject)
|
||||
|
||||
// https://github.com/cypress-io/cypress/pull/8699
|
||||
// An internal command is inserted to create a divider between
|
||||
// commands inside within() callback and commands chained to it.
|
||||
const restoreCmdIndex = state('index') + 1
|
||||
|
||||
cy.queue.insert(restoreCmdIndex, $Command.create({
|
||||
args: [subject],
|
||||
name: 'within-restore',
|
||||
fn: (subject) => subject,
|
||||
}))
|
||||
|
||||
state('index', restoreCmdIndex)
|
||||
|
||||
fn.call(ctx, subject)
|
||||
|
||||
const cleanup = () => cy.removeListener('command:start', setWithinSubject)
|
||||
|
||||
// we need a mechanism to know when we should remove
|
||||
// our withinSubject so we dont accidentally keep it
|
||||
// around after the within callback is done executing
|
||||
// so when each command starts, check to see if this
|
||||
// is the command which references our 'next' and
|
||||
// if so, remove the within subject
|
||||
const setWithinSubject = (obj) => {
|
||||
if (obj !== next) {
|
||||
return
|
||||
return group(Cypress, groupOptions, (log) => {
|
||||
if (!_.isFunction(fn)) {
|
||||
$errUtils.throwErrByPath('within.invalid_argument', { onFail: log })
|
||||
}
|
||||
|
||||
// okay so what we're doing here is creating a property
|
||||
// which stores the 'next' command which will reset the
|
||||
// withinSubject. If two 'within' commands reference the
|
||||
// exact same 'next' command, then this prevents accidentally
|
||||
// resetting withinSubject more than once. If they point
|
||||
// to differnet 'next's then its okay
|
||||
if (next !== state('nextWithinSubject')) {
|
||||
state('withinSubject', prevWithinSubject || null)
|
||||
state('nextWithinSubject', next)
|
||||
}
|
||||
|
||||
// regardless nuke this listeners
|
||||
cleanup()
|
||||
}
|
||||
|
||||
// if next is defined then we know we'll eventually
|
||||
// unbind these listeners
|
||||
if (next) {
|
||||
cy.on('command:start', setWithinSubject)
|
||||
} else {
|
||||
// remove our listener if we happen to reach the end
|
||||
// event which will finalize cleanup if there was no next obj
|
||||
cy.once('command:queue:before:end', () => {
|
||||
cleanup()
|
||||
|
||||
state('withinSubject', null)
|
||||
})
|
||||
}
|
||||
|
||||
return subject
|
||||
return withinFn(subject, fn)
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ export class $Command {
|
||||
const arg = args[i]
|
||||
|
||||
if (_.isObject(arg)) {
|
||||
// filter out any properties which arent primitives
|
||||
// filter out any properties which aren't primitives
|
||||
// to prevent accidental mutations
|
||||
const opts = _.omitBy(arg, _.isObject)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user