Skip to content

Commit 43ec4af

Browse files
committed
feat(count): support above/below/at.least/at/most
1 parent af53b9e commit 43ec4af

File tree

4 files changed

+256
-17
lines changed

4 files changed

+256
-17
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ Then, we can add our assertion to the chain.
3838
- `await expect(selector).to.have.attribute('attributeName')` - Test whether [at least one] matching element has the given attribute
3939
- `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
4040
- `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
41-
- `await expect(selector).to.have.count(number)` - Test how many elements exist in the DOM with the supplied selector
41+
- `await expect(selector).to.have.count(n)` - Test that exactly `n` elements exist in the DOM with the supplied selector
42+
- `await expect(selector).to.have.count.above(n)` - Test that more than `n` elements exist in the DOM with the supplied selector
43+
- `await expect(selector).to.have.count.below(n)` - Test that less than `n` elements exist in the DOM with the supplied selector
44+
- `await expect(selector).to.have.count.at.least(n)` - Test that at least `n` elements exist in the DOM with the supplied selector
45+
- `await expect(selector).to.have.count.at.most(n)` - Test that at most `n` elements exist in the DOM with the supplied selector
4246
- `await expect(selector).to.have.value('string')` - Test that [at least one] selected element has a value matching the given string
4347
- `await expect(selector).to.have.value(/regex/)` - Test that [at least one] selected element has a value matching the given regular expression
4448
- `await expect(selector).to.have.focus()` - (alias for `to.be.focused()`)

src/assertions/count.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,28 @@
66

77
import getElements from '../util/getElements'
88

9-
const count = (client, chai, utils, options) =>
10-
async function(expected) {
11-
const [elements, selector] = await getElements(
12-
utils.flag(this, 'object'),
13-
client
14-
)
9+
const count = (client, chai, utils, options) => {
10+
async function assertCount(expected) {
11+
const { getValueAndSelector } = utils.flag(this, 'chai-webdriverio-async')
12+
const [count, selector] = await getValueAndSelector()
1513

1614
this.assert(
17-
elements.length === expected,
18-
`Expected <${selector}> to appear in the DOM ${expected} times, but it shows up ${
19-
elements.length
20-
} times instead.`,
15+
count === expected,
16+
`Expected <${selector}> to appear in the DOM ${expected} times, but it shows up ${count} times instead.`,
2117
`Expected <${selector}> not to appear in the DOM ${expected} times, but it does.`
2218
)
2319
}
20+
assertCount.chain = function chainCount() {
21+
const obj = utils.flag(this, 'object')
22+
utils.flag(this, 'chai-webdriverio-async', {
23+
type: 'count',
24+
getValueAndSelector: async () => {
25+
const [elements, selector] = await getElements(obj, client)
26+
return [elements.length, selector]
27+
},
28+
})
29+
}
30+
return assertCount
31+
}
2432

2533
export default count

src/index.js

Lines changed: 113 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import value from './assertions/value'
1212

1313
export default function(client, options = {}) {
1414
return function chaiWebdriverIO(chai, utils) {
15+
const { Assertion } = chai
16+
1517
const methodsToAdd = {
1618
attribute,
1719
clickable,
@@ -29,12 +31,117 @@ export default function(client, options = {}) {
2931

3032
for (const name in methodsToAdd) {
3133
const method = methodsToAdd[name](client, chai, utils, options)
32-
utils.addMethod(chai.Assertion.prototype, name, function() {
33-
const promise = method.apply(this, arguments)
34-
this._obj = promise
35-
this.then = promise.then.bind(promise)
36-
return this
37-
})
34+
if (typeof method.chain === 'function') {
35+
Assertion.addChainableMethod(
36+
name,
37+
function() {
38+
const promise = method.apply(this, arguments)
39+
this._obj = promise
40+
this.then = promise.then.bind(promise)
41+
return this
42+
},
43+
method.chain
44+
)
45+
} else {
46+
Assertion.addMethod(name, function() {
47+
const promise = method.apply(this, arguments)
48+
this._obj = promise
49+
this.then = promise.then.bind(promise)
50+
return this
51+
})
52+
}
3853
}
54+
55+
Assertion.overwriteMethod('above', function(_super) {
56+
return function assertAbove(n) {
57+
const ourFlag = utils.flag(this, 'chai-webdriverio-async')
58+
if (ourFlag) {
59+
return (async () => {
60+
const { getValueAndSelector } = ourFlag
61+
62+
const [value, selector] = await getValueAndSelector()
63+
64+
this.assert(
65+
value > n,
66+
`Expected <${selector}> to appear in the DOM more than #{exp} times, but it shows up #{act} times instead.`,
67+
`Expected <${selector}> not to appear in the DOM more than #{exp} times, but it shows up #{act} times instead.`,
68+
n,
69+
value
70+
)
71+
})()
72+
} else {
73+
_super.apply(this, arguments)
74+
}
75+
}
76+
})
77+
78+
Assertion.overwriteMethod('least', function(_super) {
79+
return function assertAtLeast(n) {
80+
const ourFlag = utils.flag(this, 'chai-webdriverio-async')
81+
if (ourFlag) {
82+
return (async () => {
83+
const { getValueAndSelector } = ourFlag
84+
85+
const [value, selector] = await getValueAndSelector()
86+
87+
this.assert(
88+
value >= n,
89+
`Expected <${selector}> to appear in the DOM at least #{exp} times, but it shows up #{act} times instead.`,
90+
`Expected <${selector}> not to appear in the DOM at least #{exp} times, but it shows up #{act} times instead.`,
91+
n,
92+
value
93+
)
94+
})()
95+
} else {
96+
_super.apply(this, arguments)
97+
}
98+
}
99+
})
100+
101+
Assertion.overwriteMethod('below', function(_super) {
102+
return function assertBelow(n) {
103+
const ourFlag = utils.flag(this, 'chai-webdriverio-async')
104+
if (ourFlag) {
105+
return (async () => {
106+
const { getValueAndSelector } = ourFlag
107+
108+
const [value, selector] = await getValueAndSelector()
109+
110+
this.assert(
111+
value < n,
112+
`Expected <${selector}> to appear in the DOM less than #{exp} times, but it shows up #{act} times instead.`,
113+
`Expected <${selector}> not to appear in the DOM less than #{exp} times, but it shows up #{act} times instead.`,
114+
n,
115+
value
116+
)
117+
})()
118+
} else {
119+
_super.apply(this, arguments)
120+
}
121+
}
122+
})
123+
124+
Assertion.overwriteMethod('most', function(_super) {
125+
return function assertAtMost(n) {
126+
const ourFlag = utils.flag(this, 'chai-webdriverio-async')
127+
if (ourFlag) {
128+
return (async () => {
129+
const { getValueAndSelector } = ourFlag
130+
131+
const [value, selector] = await getValueAndSelector()
132+
133+
this.assert(
134+
value <= n,
135+
`Expected <${selector}> to appear in the DOM at most #{exp} times, but it shows up #{act} times instead.`,
136+
`Expected <${selector}> not to appear in the DOM at most #{exp} times, but it shows up #{act} times instead.`,
137+
n,
138+
value
139+
)
140+
})()
141+
} else {
142+
_super.apply(this, arguments)
143+
}
144+
}
145+
})
39146
}
40147
}

test/assertions/count-test.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,124 @@ describe('count', () => {
5454
)
5555
})
5656
})
57+
describe(`when not negated with above`, function() {
58+
it(`resolves when element count is above expectation`, async function() {
59+
await expect('.some-selector').to.have.count.above(1)
60+
await expect('.some-selector').to.have.count.above(0)
61+
})
62+
it(`rejects when element count is not above expectation`, async function() {
63+
await expect(
64+
expect('.some-selector')
65+
.to.have.count.above(2)
66+
.then(null)
67+
).to.be.rejectedWith(
68+
'Expected <.some-selector> to appear in the DOM more than 2 times, but it shows up 2 times instead.'
69+
)
70+
})
71+
})
72+
describe(`when negated with above`, function() {
73+
it(`resolves when element count is not above expectation`, async function() {
74+
await expect('.some-selector').to.not.have.count.above(2)
75+
await expect('.some-selector').to.not.have.count.above(3)
76+
})
77+
it(`rejects when element count is above expectation`, async function() {
78+
await expect(
79+
expect('.some-selector')
80+
.to.not.have.count.above(1)
81+
.then(null)
82+
).to.be.rejectedWith(
83+
'Expected <.some-selector> not to appear in the DOM more than 1 times, but it shows up 2 times instead.'
84+
)
85+
})
86+
})
87+
describe(`when not negated with at.least`, function() {
88+
it(`resolves when element count is at least expectation`, async function() {
89+
await expect('.some-selector').to.have.count.at.least(2)
90+
await expect('.some-selector').to.have.count.at.least(1)
91+
})
92+
it(`rejects when element count is not at least expectation`, async function() {
93+
await expect(
94+
expect('.some-selector')
95+
.to.have.count.at.least(3)
96+
.then(null)
97+
).to.be.rejectedWith(
98+
'Expected <.some-selector> to appear in the DOM at least 3 times, but it shows up 2 times instead.'
99+
)
100+
})
101+
})
102+
describe(`when negated with at.least`, function() {
103+
it(`resolves when element count is not at least expectation`, async function() {
104+
await expect('.some-selector').to.not.have.count.at.least(3)
105+
await expect('.some-selector').to.not.have.count.at.least(4)
106+
})
107+
it(`rejects when element count is at least expectation`, async function() {
108+
await expect(
109+
expect('.some-selector')
110+
.to.not.have.count.at.least(2)
111+
.then(null)
112+
).to.be.rejectedWith(
113+
'Expected <.some-selector> not to appear in the DOM at least 2 times, but it shows up 2 times instead.'
114+
)
115+
})
116+
})
117+
describe(`when not negated with below`, function() {
118+
it(`resolves when element count is below expectation`, async function() {
119+
await expect('.some-selector').to.have.count.below(3)
120+
await expect('.some-selector').to.have.count.below(4)
121+
})
122+
it(`rejects when element count is not below expectation`, async function() {
123+
await expect(
124+
expect('.some-selector')
125+
.to.have.count.below(2)
126+
.then(null)
127+
).to.be.rejectedWith(
128+
'Expected <.some-selector> to appear in the DOM less than 2 times, but it shows up 2 times instead.'
129+
)
130+
})
131+
})
132+
describe(`when negated with below`, function() {
133+
it(`resolves when element count is not below expectation`, async function() {
134+
await expect('.some-selector').to.not.have.count.below(2)
135+
await expect('.some-selector').to.not.have.count.below(1)
136+
})
137+
it(`rejects when element count is not below expectation`, async function() {
138+
await expect(
139+
expect('.some-selector')
140+
.to.not.have.count.below(3)
141+
.then(null)
142+
).to.be.rejectedWith(
143+
'Expected <.some-selector> not to appear in the DOM less than 3 times, but it shows up 2 times instead.'
144+
)
145+
})
146+
})
147+
describe(`when not negated with at.most`, function() {
148+
it(`resolves when element count is at most expectation`, async function() {
149+
await expect('.some-selector').to.have.count.at.most(2)
150+
await expect('.some-selector').to.have.count.at.most(3)
151+
})
152+
it(`rejects when element count is not at most expectation`, async function() {
153+
await expect(
154+
expect('.some-selector')
155+
.to.have.count.at.most(1)
156+
.then(null)
157+
).to.be.rejectedWith(
158+
'Expected <.some-selector> to appear in the DOM at most 1 times, but it shows up 2 times instead.'
159+
)
160+
})
161+
})
162+
describe(`when negated with at.most`, function() {
163+
it(`resolves when element count is not at most expectation`, async function() {
164+
await expect('.some-selector').to.not.have.count.at.most(1)
165+
await expect('.some-selector').to.not.have.count.at.most(0)
166+
})
167+
it(`rejects when element count is at most expectation`, async function() {
168+
await expect(
169+
expect('.some-selector')
170+
.to.not.have.count.at.most(2)
171+
.then(null)
172+
).to.be.rejectedWith(
173+
'Expected <.some-selector> not to appear in the DOM at most 2 times, but it shows up 2 times instead.'
174+
)
175+
})
176+
})
57177
})

0 commit comments

Comments
 (0)