mirror of
https://github.com/cypress-io/cypress.git
synced 2026-01-31 03:29:43 -06:00
cast numbers to strings when accessing assertions which always yield string subjects (#7315)
Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
This commit is contained in:
@@ -13,7 +13,7 @@ const selectors = {
|
||||
focused: 'focused',
|
||||
}
|
||||
|
||||
const attrs = {
|
||||
const accessors = {
|
||||
attr: 'attribute',
|
||||
css: 'CSS property',
|
||||
prop: 'property',
|
||||
@@ -25,6 +25,12 @@ const attrs = {
|
||||
// the methods on it
|
||||
const wrap = (ctx) => $(ctx._obj)
|
||||
|
||||
const maybeCastNumberToString = (num) => {
|
||||
// if this is a finite number (no Infinity or NaN)
|
||||
// cast to a string
|
||||
return _.isFinite(num) ? `${num}` : num
|
||||
}
|
||||
|
||||
const $chaiJquery = (chai, chaiUtils, callbacks = {}) => {
|
||||
const { inspect, flag } = chaiUtils
|
||||
|
||||
@@ -111,6 +117,8 @@ const $chaiJquery = (chai, chaiUtils, callbacks = {}) => {
|
||||
})
|
||||
|
||||
chai.Assertion.addMethod('id', function (id) {
|
||||
id = maybeCastNumberToString(id)
|
||||
|
||||
return assert(
|
||||
this,
|
||||
'id',
|
||||
@@ -145,6 +153,8 @@ const $chaiJquery = (chai, chaiUtils, callbacks = {}) => {
|
||||
})
|
||||
|
||||
chai.Assertion.addMethod('text', function (text) {
|
||||
text = maybeCastNumberToString(text)
|
||||
|
||||
assertDom(
|
||||
this,
|
||||
'text',
|
||||
@@ -168,6 +178,8 @@ const $chaiJquery = (chai, chaiUtils, callbacks = {}) => {
|
||||
})
|
||||
|
||||
chai.Assertion.addMethod('value', function (value) {
|
||||
value = maybeCastNumberToString(value)
|
||||
|
||||
assertDom(
|
||||
this,
|
||||
'value',
|
||||
@@ -250,23 +262,23 @@ const $chaiJquery = (chai, chaiUtils, callbacks = {}) => {
|
||||
})
|
||||
})
|
||||
|
||||
_.each(attrs, (description, attr) => {
|
||||
return chai.Assertion.addMethod(attr, function (name, val) {
|
||||
_.each(accessors, (description, accessor) => {
|
||||
return chai.Assertion.addMethod(accessor, function (name, val) {
|
||||
assertDom(
|
||||
this,
|
||||
attr,
|
||||
accessor,
|
||||
`expected #{this} to have ${description} #{exp}`,
|
||||
`expected #{this} not to have ${description} #{exp}`,
|
||||
name,
|
||||
)
|
||||
|
||||
const actual = wrap(this)[attr](name)
|
||||
const actual = wrap(this)[accessor](name)
|
||||
|
||||
// when we only have 1 argument dont worry about val
|
||||
if (arguments.length === 1) {
|
||||
assert(
|
||||
this,
|
||||
attr,
|
||||
accessor,
|
||||
actual !== undefined,
|
||||
`expected #{this} to have ${description} #{exp}`,
|
||||
`expected #{this} not to have ${description} #{exp}`,
|
||||
@@ -276,7 +288,7 @@ const $chaiJquery = (chai, chaiUtils, callbacks = {}) => {
|
||||
// change the subject
|
||||
this._obj = actual
|
||||
} else {
|
||||
// if we don't have an attribute here at all we need to
|
||||
// if we don't have an accessor here at all we need to
|
||||
// have a different failure message
|
||||
let message; let negatedMessage
|
||||
|
||||
@@ -290,9 +302,17 @@ const $chaiJquery = (chai, chaiUtils, callbacks = {}) => {
|
||||
negatedMessage = `expected \#{this} not to have ${description} ${inspect(name)} with the value \#{exp}, but the value was \#{act}`
|
||||
}
|
||||
|
||||
// only cast .attr() as a string
|
||||
// since prop stores the native javascript type
|
||||
// and we don't want to optimistically cast those
|
||||
// values as a string
|
||||
if (accessor === 'attr') {
|
||||
val = maybeCastNumberToString(val)
|
||||
}
|
||||
|
||||
assert(
|
||||
this,
|
||||
attr,
|
||||
accessor,
|
||||
(actual != null) && (actual === val),
|
||||
message,
|
||||
negatedMessage,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<body>
|
||||
<span id="foo">foo<span>
|
||||
<div>div</div>
|
||||
<input />
|
||||
<input id="input" />
|
||||
<button>button</button>
|
||||
<ul id="list">
|
||||
<li>li 0</li>
|
||||
@@ -16,6 +16,12 @@
|
||||
<div>
|
||||
Nested Find
|
||||
</div>
|
||||
<span id="number" class="999">123</span>
|
||||
<span id="456">span with id=number</span>
|
||||
<span id="data-number" data-number='222'>span with data-number=number</span>
|
||||
<input id="value-number" value=123 />
|
||||
<span id="attr-number" num="777">span with attr=number</span>
|
||||
<span id="prop-number">span with prop=number</span>
|
||||
<!-- cy.visit() fails when element with id="jquery" exists
|
||||
// https://github.com/cypress-io/cypress/issues/6193 -->
|
||||
<p id="jquery">jQuery</p>
|
||||
|
||||
@@ -1316,6 +1316,14 @@ describe('src/cy/commands/assertions', () => {
|
||||
expect(this.logs.length).to.eq(8)
|
||||
})
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/7314
|
||||
it('supports a number argument', () => {
|
||||
cy.get('#data-number').then(($el) => {
|
||||
expect($el).to.have.data('number', 222)
|
||||
expect($el).not.to.have.data('number', '222')
|
||||
})
|
||||
})
|
||||
|
||||
it('throws when obj is not DOM', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(this.logs.length).to.eq(1)
|
||||
@@ -1357,6 +1365,14 @@ describe('src/cy/commands/assertions', () => {
|
||||
)
|
||||
})
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/7314
|
||||
it('supports a number argument', () => {
|
||||
cy.get('.999').then(($el) => {
|
||||
expect($el).to.have.class(999)
|
||||
expect($el).to.have.class('999')
|
||||
})
|
||||
})
|
||||
|
||||
it('throws when obj is not DOM', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(this.logs.length).to.eq(1)
|
||||
@@ -1428,6 +1444,14 @@ describe('src/cy/commands/assertions', () => {
|
||||
)
|
||||
})
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/7314
|
||||
it('supports a number argument', () => {
|
||||
cy.get('#456').then(($el) => {
|
||||
expect($el).to.have.id(456)
|
||||
expect($el).to.have.id('456')
|
||||
})
|
||||
})
|
||||
|
||||
it('throws when obj is not DOM', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(this.logs.length).to.eq(1)
|
||||
@@ -1581,6 +1605,13 @@ describe('src/cy/commands/assertions', () => {
|
||||
}
|
||||
})
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/7314
|
||||
it('supports a number argument', () => {
|
||||
cy.get('#number').then(($el) => {
|
||||
expect($el).to.have.text(123)
|
||||
})
|
||||
})
|
||||
|
||||
it('partial match', function () {
|
||||
expect(this.$div).to.have.text('foo')
|
||||
expect(this.$div).to.contain.text('o')
|
||||
@@ -1663,6 +1694,14 @@ describe('src/cy/commands/assertions', () => {
|
||||
}
|
||||
})
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/7314
|
||||
it('supports a number argument', () => {
|
||||
cy.get('#value-number').then(($el) => {
|
||||
expect($el).to.have.value(123)
|
||||
expect($el).to.have.value('123')
|
||||
})
|
||||
})
|
||||
|
||||
it('throws when obj is not DOM', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(this.logs.length).to.eq(1)
|
||||
@@ -2431,6 +2470,14 @@ describe('src/cy/commands/assertions', () => {
|
||||
)
|
||||
})
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/7314
|
||||
it('supports a number argument', () => {
|
||||
cy.get('#attr-number').then(($el) => {
|
||||
expect($el).to.have.attr('num', 777)
|
||||
expect($el).to.have.attr('num', '777')
|
||||
})
|
||||
})
|
||||
|
||||
it('throws when obj is not DOM', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(this.logs.length).to.eq(1)
|
||||
@@ -2534,6 +2581,19 @@ describe('src/cy/commands/assertions', () => {
|
||||
)
|
||||
})
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/7314
|
||||
it('supports a number argument', () => {
|
||||
cy.get('#prop-number').then(($el) => {
|
||||
$el.prop('foo', 444)
|
||||
$el.prop('bar', '333')
|
||||
|
||||
expect($el).to.have.prop('foo', 444)
|
||||
expect($el).not.to.have.prop('foo', '444')
|
||||
expect($el).not.to.have.prop('bar', 333)
|
||||
expect($el).to.have.prop('bar', '333')
|
||||
})
|
||||
})
|
||||
|
||||
it('throws when obj is not DOM', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(this.logs.length).to.eq(1)
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('keyboard', () => {
|
||||
it('fires keyboard and click events with modifier', () => {
|
||||
cy
|
||||
.window().then((win) => {
|
||||
win.$('input').one('keyup', (e) => {
|
||||
win.$('#input').one('keyup', (e) => {
|
||||
expect(e.ctrlKey).to.be.true
|
||||
|
||||
expect(e.which).to.equal(83)
|
||||
@@ -17,7 +17,7 @@ describe('keyboard', () => {
|
||||
expect(e.ctrlKey).to.be.true
|
||||
})
|
||||
|
||||
cy.get('input').type('{ctrl}s', { release: false })
|
||||
cy.get('#input').type('{ctrl}s', { release: false })
|
||||
|
||||
cy.get('button').click()
|
||||
})
|
||||
@@ -26,11 +26,11 @@ describe('keyboard', () => {
|
||||
it('releases modifiers between tests', () => {
|
||||
cy
|
||||
.window().then((win) => {
|
||||
win.$('input').one('keyup', (e) => {
|
||||
win.$('#input').one('keyup', (e) => {
|
||||
expect(e.ctrlKey).to.be.false
|
||||
})
|
||||
|
||||
cy.get('input').type('s')
|
||||
cy.get('#input').type('s')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -48,28 +48,28 @@ describe('keyboard', () => {
|
||||
characters.forEach(([char, asciiCode, keyCode]) => {
|
||||
it(`for ${char}`, () => {
|
||||
cy.window().then((win) => {
|
||||
win.$('input').one('keydown', (e) => {
|
||||
win.$('#input').one('keydown', (e) => {
|
||||
expect(e.charCode).to.equal(0)
|
||||
expect(e.which).to.equal(keyCode)
|
||||
|
||||
expect(e.keyCode).to.equal(keyCode)
|
||||
})
|
||||
|
||||
win.$('input').one('keypress', (e) => {
|
||||
win.$('#input').one('keypress', (e) => {
|
||||
expect(e.charCode).to.equal(asciiCode)
|
||||
expect(e.which).to.equal(asciiCode)
|
||||
|
||||
expect(e.keyCode).to.equal(asciiCode)
|
||||
})
|
||||
|
||||
win.$('input').one('keyup', (e) => {
|
||||
win.$('#input').one('keyup', (e) => {
|
||||
expect(e.charCode).to.equal(0)
|
||||
expect(e.which).to.equal(keyCode)
|
||||
|
||||
expect(e.keyCode).to.equal(keyCode)
|
||||
})
|
||||
|
||||
cy.get('input').type(char)
|
||||
cy.get('#input').type(char)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user