Skip to content

Commit

Permalink
Merge pull request #8 from sveyret/feature/members
Browse files Browse the repository at this point in the history
Add members feature
  • Loading branch information
sveyret authored Nov 14, 2022
2 parents 7ff0300 + e53d8d8 commit 29c6354
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 1 deletion.
47 changes: 47 additions & 0 deletions doc/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ expect({x = {a = 1}}).to.have.deep.property('x', {a = 1})
expect({x = {a = 1}}).to.Not.have.property('x', {a = 1})
```

## ordered

Causes some assertions that follow in the chain to respect expected order.

```lua
expect({1, 2, 3}).to.have.ordered.members(1, 2).but.Not.to.have.ordered.members(2, 1)
```

## a(type)

Asserts that the target’s type is equal to the given string type. Types are case insensitive.
Expand Down Expand Up @@ -326,6 +334,45 @@ Asserts that the target matches the given pattern.
expect('foo').to.match('^f.o$')
```

## members(member1[, member2[, ...]])

Asserts that the target array has the same members as the given members.

```lua
expect({1, 2, 3}).to.have.members(2, 1, 3)
expect({1, 2, 2}).to.have.members(2, 1, 2)
```

By default, members are compared using strict equality. Add `deep` earlier in the chain to use deep equality
instead.

```lua
expect({{a = 1}}).to.have.deep.members({a = 1})
expect({{a = 1}}).to.Not.have.members({a = 1})
```

By default, order doesn’t matter. Add `ordered` earlier in the chain to require that members appear in the
same order.

```lua
expect({1, 2, 3}).to.have.ordered.members(1, 2, 3)
expect({1, 2, 3}).to.have.ordered.members(2, 1, 3).but.Not.ordered.members(2, 1, 3)
```

By default, both target and given members must be the same size. Add `include` earlier in the chain to
require that the target’s members be a superset of the expected members.

```lua
expect({1, 2, 3}).to.include.members(1, 2)
expect({1, 2, 3}).to.include.members(2, 3)
```

`deep`, `ordered` and `include` can all be combined.

```lua
expect({{a = 1}, {b = 2}, {c = 3}}).to.include.deep.ordered.members({b = 2}, {c = 3})
```

## most(n)

Asserts that the target is a number less than or equal to the given number `n`.
Expand Down
2 changes: 1 addition & 1 deletion expect/Utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function Utils.isArray(item)
local max = 0
local count = 0
for k, v in pairs(item) do
if type(k) == 'number' then
if type(k) == 'number' and k > 0 and math.floor(k) == k then
if k > max then
max = k
end
Expand Down
63 changes: 63 additions & 0 deletions expect/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ return function(expect)
controlData.deep = true
end)

-- Set ordered flag
expect.addProperty('ordered', function(controlData)
controlData.ordered = true
end)

-- Set any flag
expect.addProperty('any', function(controlData)
controlData.any = true
Expand Down Expand Up @@ -452,4 +457,62 @@ return function(expect)
end
expect.addMethod('closeTo', expectCloseTo)
expect.addMethod('approximately', expectCloseTo)

-- Check object has members
expect.addMethod('members', function(controlData, ...)
local maxIndex = Utils.isArray(controlData.actual)
controlData:assert(maxIndex, FailureMessage('expected {#} to be an array'))

local expected = {...}
local ok = true

for i = 1, maxIndex do
if controlData.actual[i] then
if #expected < 1 then
ok = controlData.contains
break
end
local found = false
for e = 1, #expected do
if controlData.ordered and e ~= 1 then
break
end
if controlData:areSame(expected[e], controlData.actual[i]) then
found = true
table.remove(expected, e)
break
end
end
if not found and not controlData.contains then
ok = false
break
end
end
end
ok = ok and #expected < 1

local params = {
members = setmetatable({...}, {
__tostring = function(members)
local result = ''
for i = 1, #members do
if i > 1 then
result = result .. ', '
end
result = result .. tostring(members[i])
end
return result
end
})
}
if controlData.contains then
params.ordered = 'an ordered ' or 'a '
controlData:assert(ok, FailureMessage('expected {#} to be {!ordered}superset of {!members}', params),
FailureMessage('expected {#} to not be {!ordered}superset of {!members}', params))
else
params.ordered = controlData.ordered and 'ordered ' or ''
controlData:assert(ok, FailureMessage('expected {#} to have the same {!ordered}members as {!members}', params),
FailureMessage('expected {#} to not have the same {!ordered}members as {!members}', params))
end
end)
end
78 changes: 78 additions & 0 deletions spec/expect/core_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -966,4 +966,82 @@ describe('expect', function()
expect(1.5).Not.to.be.closeTo(1.2, 0.5)
end, 'expected (number) 1.5 not to be close to 1.2 +/- 0.5', true)
end)

describe('members', function()
describe('(positive)', function()
case('if target has same unordered members', function()
expect({1, 2, 3}).to.have.members(2, 1, 3)
end)

case('if target has same duplicated members', function()
expect({1, 2, 2}).to.have.members(2, 1, 2)
end)

case('if target has same table members', function()
expect({{
a = 1
}}).to.have.members({
a = 1
})
end, 'expected %(table.* to have the same members as table.*')

case('if target has same table members with deep comparison', function()
expect({{
a = 1
}}).to.have.deep.members({
a = 1
})
end)

case('if target does not have same members', function()
expect({1, 2, 3}).to.have.members(2, 4, 3)
end, 'expected %(table.* to have the same members as 2, 4, 3$')

case('if target has less members', function()
expect({1, 2, 3}).to.have.members(2, 1, 3, 4)
end, 'expected %(table.* to have the same members as 2, 1, 3, 4$')

case('if target has more members', function()
expect({1, 2, 3}).to.have.members(2, 1)
end, 'expected %(table.* to have the same members as 2, 1$')

case('if target has same unordered members with ordered comparison', function()
expect({1, 2, 3}).to.have.ordered.members(2, 1, 3)
end, 'expected %(table.* to have the same ordered members as 2, 1, 3')

case('if target has same ordered members', function()
expect({1, 2, 3}).to.have.ordered.members(1, 2, 3)
end)

case('if target has more members with include', function()
expect({1, 2, 3}).to.include.members(2, 1)
end)

case('if target has more ordered members with include', function()
expect({1, 2, 3}).to.include.ordered.members(2, 3)
end)
end)

describe('(negative)', function()
case('if target has same unordered members', function()
expect({1, 2, 3}).to.Not.have.members(2, 1, 3)
end, 'expected %(table.* to not have the same members as 2, 1, 3$')

case('if target does not have same members', function()
expect({1, 2, 3}).to.Not.have.members(2, 4, 3)
end)

case('if target has same unordered members with ordered comparison', function()
expect({1, 2, 3}).to.Not.have.ordered.members(2, 1, 3)
end)

case('if target has same ordered members', function()
expect({1, 2, 3}).to.Not.have.ordered.members(1, 2, 3)
end, 'expected %(table.* to not have the same ordered members as 1, 2, 3$')

case('if target has more members with include', function()
expect({1, 2, 3}).to.Not.include.members(2, 1)
end, 'expected %(table.* to not be an ordered superset of 2, 1$')
end)
end)
end)

0 comments on commit 29c6354

Please sign in to comment.