Additional utility functions for testing tables and table contents. The functions are roughhly equal to the same functions in Yonabas Moses library. [1]

Note that even if they are similar they are not exact copies, and that some rework of the calling code must be expected if this small lib is replaced with Moses

The module is imported the usual way with a require, and then the members can be accessed

local utils = require 'Module:BDD/utils'



-- utility module for the Behavior Driven Development testing framework
-- @provenance ideas from Moses [https://github.com/Yonaba/Moses/blob/master/moses.lua]
-- © John Erling Blad, Creative Commons by Attribution 3.0

-- @var table holding the modules exported members
local utils = {}

-- raw count of all the items in the provided table
-- @provenance reformatted exported version of 'local function count(t)' in Moses
-- @param t table that has its entries counted
-- @return count of raw entries
function utils.count( t )
	local i = 0
		for k,v in pairs( t ) do
			i = i + 1
		end
	return i
end

-- size based on the raw count
-- @provenance reformatted exported version of 'function _.size(...)' in Moses
-- @param optional [table|any] count entries if table, count all args otherwise
-- @return count of entries
function utils.size(...)
	local args = {...}
	local arg1 = args[1]
	if arg1 == nil then
		return 0
	elseif type( arg1 ) == 'table' then
		return utils.count( args[1] )
	end
	-- placement differs from Moses
	return utils.count( args )
end

-- deep equal of two objects
-- @provenance changed exported version of 'function UnitTester:equals_deep(name, actual, expected, options)' in [[w:no:Module:UnitTests]]
-- @provenance reformatted exported version of 'function _.isEqual(objA, objB, useMt)' in Moses
-- @param objA any type of object
-- @param objB any type of object
-- @param useMt boolean optional indicator for whether to include the meta table
-- @return boolean result of comparison
function utils.deepEqual( objA, objB, useMt )
	local typeObjA = type( objA )
	local typeObjB = type( objB )

	if typeObjA ~= typeObjB then
		return false end
	if typeObjA ~= 'table' then
		return objA == objB
	end

	local mtA = getmetatable( objA )
	local mtB = getmetatable( objB )

	if useMt then
		if (mtA or mtB) and (mtA.__eq or mtB.__eq) then
			return mtA.__eq(objA, objB) or mtB.__eq(objB, objA) or (objA==objB)
		end
	end

	if utils.size( objA ) ~= utils.size( objB ) then
		return false
	end

	for i,v1 in pairs( objA ) do
		local v2 = objB[i]
		-- test is partly inlined, differs from Moses
		if v2 == nil or not utils.deepEqual( v1, v2, useMt ) then
			return false
		end
	end

	for i,v1 in pairs(objB) do
		local v2 = objA[i]
		-- test is inlined, differs from Moses
		if v2 == nil then
			return false
		end
	end

	return true
end

-- checks if a table contains the arg
-- @provenance reformatted exported version of 'function _.contains(t, value)' in Moses
-- @param t table that is searched for the arg
-- @param arg any item to be searched for
-- @return boolean result of the operation
function utils.contains(t, arg)
	-- inlined code from '_.toBoolean' and '_.detect' from Moses
	local cmp = (type(arg)=='function') and arg or utils.deepEqual
	for k,v in pairs(t) do
		if cmp(v, arg) then
			return k
		end
	end
	return false
end

-- return the export table
return utils