Skip to content

Commit

Permalink
feat(count): support above/below/at.least/at/most
Browse files Browse the repository at this point in the history
  • Loading branch information
jedwards1211 committed Feb 19, 2021
1 parent af53b9e commit 43ec4af
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 17 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ Then, we can add our assertion to the chain.
- `await expect(selector).to.have.attribute('attributeName')` - Test whether [at least one] matching element has the given attribute
- `await expect(selector).to.have.attribute('attributeName', 'string')` - Test the attribute value of the selected element(s) against supplied string. Succeeds if at least one element matches exactly
- `await expect(selector).to.have.attribute('attributeName', /regex/)` - Test the attribute value of the selected element(s) against supplied regular expression. Succeeds if at least one element matches exactly
- `await expect(selector).to.have.count(number)` - Test how many elements exist in the DOM with the supplied selector
- `await expect(selector).to.have.count(n)` - Test that exactly `n` elements exist in the DOM with the supplied selector
- `await expect(selector).to.have.count.above(n)` - Test that more than `n` elements exist in the DOM with the supplied selector
- `await expect(selector).to.have.count.below(n)` - Test that less than `n` elements exist in the DOM with the supplied selector
- `await expect(selector).to.have.count.at.least(n)` - Test that at least `n` elements exist in the DOM with the supplied selector
- `await expect(selector).to.have.count.at.most(n)` - Test that at most `n` elements exist in the DOM with the supplied selector
- `await expect(selector).to.have.value('string')` - Test that [at least one] selected element has a value matching the given string
- `await expect(selector).to.have.value(/regex/)` - Test that [at least one] selected element has a value matching the given regular expression
- `await expect(selector).to.have.focus()` - (alias for `to.be.focused()`)
Expand Down
28 changes: 18 additions & 10 deletions src/assertions/count.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,28 @@

import getElements from '../util/getElements'

const count = (client, chai, utils, options) =>
async function(expected) {
const [elements, selector] = await getElements(
utils.flag(this, 'object'),
client
)
const count = (client, chai, utils, options) => {
async function assertCount(expected) {
const { getValueAndSelector } = utils.flag(this, 'chai-webdriverio-async')
const [count, selector] = await getValueAndSelector()

this.assert(
elements.length === expected,
`Expected <${selector}> to appear in the DOM ${expected} times, but it shows up ${
elements.length
} times instead.`,
count === expected,
`Expected <${selector}> to appear in the DOM ${expected} times, but it shows up ${count} times instead.`,
`Expected <${selector}> not to appear in the DOM ${expected} times, but it does.`
)
}
assertCount.chain = function chainCount() {
const obj = utils.flag(this, 'object')
utils.flag(this, 'chai-webdriverio-async', {
type: 'count',
getValueAndSelector: async () => {
const [elements, selector] = await getElements(obj, client)
return [elements.length, selector]
},
})
}
return assertCount
}

export default count
119 changes: 113 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import value from './assertions/value'

export default function(client, options = {}) {
return function chaiWebdriverIO(chai, utils) {
const { Assertion } = chai

const methodsToAdd = {
attribute,
clickable,
Expand All @@ -29,12 +31,117 @@ export default function(client, options = {}) {

for (const name in methodsToAdd) {
const method = methodsToAdd[name](client, chai, utils, options)
utils.addMethod(chai.Assertion.prototype, name, function() {
const promise = method.apply(this, arguments)
this._obj = promise
this.then = promise.then.bind(promise)
return this
})
if (typeof method.chain === 'function') {
Assertion.addChainableMethod(
name,
function() {
const promise = method.apply(this, arguments)
this._obj = promise
this.then = promise.then.bind(promise)
return this
},
method.chain
)
} else {
Assertion.addMethod(name, function() {
const promise = method.apply(this, arguments)
this._obj = promise
this.then = promise.then.bind(promise)
return this
})
}
}

Assertion.overwriteMethod('above', function(_super) {
return function assertAbove(n) {
const ourFlag = utils.flag(this, 'chai-webdriverio-async')
if (ourFlag) {
return (async () => {
const { getValueAndSelector } = ourFlag

const [value, selector] = await getValueAndSelector()

this.assert(
value > n,
`Expected <${selector}> to appear in the DOM more than #{exp} times, but it shows up #{act} times instead.`,
`Expected <${selector}> not to appear in the DOM more than #{exp} times, but it shows up #{act} times instead.`,
n,
value
)
})()
} else {
_super.apply(this, arguments)
}
}
})

Assertion.overwriteMethod('least', function(_super) {
return function assertAtLeast(n) {
const ourFlag = utils.flag(this, 'chai-webdriverio-async')
if (ourFlag) {
return (async () => {
const { getValueAndSelector } = ourFlag

const [value, selector] = await getValueAndSelector()

this.assert(
value >= n,
`Expected <${selector}> to appear in the DOM at least #{exp} times, but it shows up #{act} times instead.`,
`Expected <${selector}> not to appear in the DOM at least #{exp} times, but it shows up #{act} times instead.`,
n,
value
)
})()
} else {
_super.apply(this, arguments)
}
}
})

Assertion.overwriteMethod('below', function(_super) {
return function assertBelow(n) {
const ourFlag = utils.flag(this, 'chai-webdriverio-async')
if (ourFlag) {
return (async () => {
const { getValueAndSelector } = ourFlag

const [value, selector] = await getValueAndSelector()

this.assert(
value < n,
`Expected <${selector}> to appear in the DOM less than #{exp} times, but it shows up #{act} times instead.`,
`Expected <${selector}> not to appear in the DOM less than #{exp} times, but it shows up #{act} times instead.`,
n,
value
)
})()
} else {
_super.apply(this, arguments)
}
}
})

Assertion.overwriteMethod('most', function(_super) {
return function assertAtMost(n) {
const ourFlag = utils.flag(this, 'chai-webdriverio-async')
if (ourFlag) {
return (async () => {
const { getValueAndSelector } = ourFlag

const [value, selector] = await getValueAndSelector()

this.assert(
value <= n,
`Expected <${selector}> to appear in the DOM at most #{exp} times, but it shows up #{act} times instead.`,
`Expected <${selector}> not to appear in the DOM at most #{exp} times, but it shows up #{act} times instead.`,
n,
value
)
})()
} else {
_super.apply(this, arguments)
}
}
})
}
}
120 changes: 120 additions & 0 deletions test/assertions/count-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,124 @@ describe('count', () => {
)
})
})
describe(`when not negated with above`, function() {
it(`resolves when element count is above expectation`, async function() {
await expect('.some-selector').to.have.count.above(1)
await expect('.some-selector').to.have.count.above(0)
})
it(`rejects when element count is not above expectation`, async function() {
await expect(
expect('.some-selector')
.to.have.count.above(2)
.then(null)
).to.be.rejectedWith(
'Expected <.some-selector> to appear in the DOM more than 2 times, but it shows up 2 times instead.'
)
})
})
describe(`when negated with above`, function() {
it(`resolves when element count is not above expectation`, async function() {
await expect('.some-selector').to.not.have.count.above(2)
await expect('.some-selector').to.not.have.count.above(3)
})
it(`rejects when element count is above expectation`, async function() {
await expect(
expect('.some-selector')
.to.not.have.count.above(1)
.then(null)
).to.be.rejectedWith(
'Expected <.some-selector> not to appear in the DOM more than 1 times, but it shows up 2 times instead.'
)
})
})
describe(`when not negated with at.least`, function() {
it(`resolves when element count is at least expectation`, async function() {
await expect('.some-selector').to.have.count.at.least(2)
await expect('.some-selector').to.have.count.at.least(1)
})
it(`rejects when element count is not at least expectation`, async function() {
await expect(
expect('.some-selector')
.to.have.count.at.least(3)
.then(null)
).to.be.rejectedWith(
'Expected <.some-selector> to appear in the DOM at least 3 times, but it shows up 2 times instead.'
)
})
})
describe(`when negated with at.least`, function() {
it(`resolves when element count is not at least expectation`, async function() {
await expect('.some-selector').to.not.have.count.at.least(3)
await expect('.some-selector').to.not.have.count.at.least(4)
})
it(`rejects when element count is at least expectation`, async function() {
await expect(
expect('.some-selector')
.to.not.have.count.at.least(2)
.then(null)
).to.be.rejectedWith(
'Expected <.some-selector> not to appear in the DOM at least 2 times, but it shows up 2 times instead.'
)
})
})
describe(`when not negated with below`, function() {
it(`resolves when element count is below expectation`, async function() {
await expect('.some-selector').to.have.count.below(3)
await expect('.some-selector').to.have.count.below(4)
})
it(`rejects when element count is not below expectation`, async function() {
await expect(
expect('.some-selector')
.to.have.count.below(2)
.then(null)
).to.be.rejectedWith(
'Expected <.some-selector> to appear in the DOM less than 2 times, but it shows up 2 times instead.'
)
})
})
describe(`when negated with below`, function() {
it(`resolves when element count is not below expectation`, async function() {
await expect('.some-selector').to.not.have.count.below(2)
await expect('.some-selector').to.not.have.count.below(1)
})
it(`rejects when element count is not below expectation`, async function() {
await expect(
expect('.some-selector')
.to.not.have.count.below(3)
.then(null)
).to.be.rejectedWith(
'Expected <.some-selector> not to appear in the DOM less than 3 times, but it shows up 2 times instead.'
)
})
})
describe(`when not negated with at.most`, function() {
it(`resolves when element count is at most expectation`, async function() {
await expect('.some-selector').to.have.count.at.most(2)
await expect('.some-selector').to.have.count.at.most(3)
})
it(`rejects when element count is not at most expectation`, async function() {
await expect(
expect('.some-selector')
.to.have.count.at.most(1)
.then(null)
).to.be.rejectedWith(
'Expected <.some-selector> to appear in the DOM at most 1 times, but it shows up 2 times instead.'
)
})
})
describe(`when negated with at.most`, function() {
it(`resolves when element count is not at most expectation`, async function() {
await expect('.some-selector').to.not.have.count.at.most(1)
await expect('.some-selector').to.not.have.count.at.most(0)
})
it(`rejects when element count is at most expectation`, async function() {
await expect(
expect('.some-selector')
.to.not.have.count.at.most(2)
.then(null)
).to.be.rejectedWith(
'Expected <.some-selector> not to appear in the DOM at most 2 times, but it shows up 2 times instead.'
)
})
})
})

0 comments on commit 43ec4af

Please sign in to comment.