Skip to content

Commit

Permalink
(object) test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
dmonad committed Mar 10, 2019
1 parent 321d50c commit 6c9b113
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 12 deletions.
53 changes: 45 additions & 8 deletions object.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@

export const create = Object.create(null)
/**
* @return {Object<string,any>} obj
*/
export const create = () => Object.create(null)

/**
* @param {Object<string,any>} obj
*/
export const keys = Object.keys

/**
* @template V
* @param {Object<string,V>} obj
* @param {function(V,string):any} f
* @param {Object<string,any>} obj
* @param {function(any,string):any} f
*/
export const forEach = (obj, f) => {
for (let key in obj) {
f(obj[key], key)
}
}

/**
* @template R
* @param {Object<string,any>} obj
* @param {function(any,string):R} f
* @return {Array<R>}
*/
export const map = (obj, f) => {
const results = []
for (let key in obj) {
Expand All @@ -22,8 +33,31 @@ export const map = (obj, f) => {
return results
}

export const length = obj => Object.keys(obj).length
/**
* @param {Object<string,any>} obj
* @return {number}
*/
export const length = obj => keys(obj).length

/**
* @param {Object<string,any>} obj
* @param {function(any,string):boolean} f
* @return {boolean}
*/
export const some = (obj, f) => {
for (let key in obj) {
if (f(obj[key], key)) {
return true
}
}
return false
}

/**
* @param {Object<string,any>} obj
* @param {function(any,string):boolean} f
* @return {boolean}
*/
export const every = (obj, f) => {
for (let key in obj) {
if (!f(obj[key], key)) {
Expand All @@ -33,6 +67,9 @@ export const every = (obj, f) => {
return true
}

export const some = (obj, f) => every(obj, () => !f())

export const equalFlat = (a, b) => a === b || (length(a) === length(b) && every(a, (val, key) => b[key] === val))
/**
* @param {Object<string,any>} a
* @param {Object<string,any>} b
* @return {boolean}
*/
export const equalFlat = (a, b) => a === b || (length(a) === length(b) && every(a, (val, key) => (val !== undefined || b.hasOwnProperty(key)) && b[key] === val))
31 changes: 31 additions & 0 deletions object.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as t from './testing.js'
import * as object from './object.js'
import * as math from './math.js'

export const testObject = tc => {
t.assert(object.create().constructor === undefined, 'object.create creates an empty object without constructor')
t.describe('object.equalFlat')
t.assert(object.equalFlat({}, {}), 'comparing equal objects')
t.assert(object.equalFlat({ 'x': 1 }, { 'x': 1 }), 'comparing equal objects')
t.assert(object.equalFlat({ x: 'dtrn' }, { x: 'dtrn' }), 'comparing equal objects')
t.assert(!object.equalFlat({ x: {} }, { x: {} }), 'flatEqual does not dive deep')
t.assert(object.equalFlat({ x: undefined }, { x: undefined }), 'flatEqual handles undefined')
t.assert(!object.equalFlat({ x: undefined }, { y: {} }), 'flatEqual handles undefined')
t.describe('object.every')
t.assert(object.every({ a: 1, b: 3 }, (v, k) => (v % 2) === 1 && k !== 'c'))
t.assert(!object.every({ a: 1, b: 3, c: 5 }, (v, k) => (v % 2) === 1 && k !== 'c'))
t.describe('object.some')
t.assert(object.some({ a: 1, b: 3 }, (v, k) => v === 3 && k === 'b'))
t.assert(!object.some({ a: 1, b: 5 }, (v, k) => v === 3))
t.assert(object.some({ a: 1, b: 5 }, () => true))
t.assert(!object.some({ a: 1, b: 5 }, (v, k) => false))
t.describe('object.forEach')
let forEachSum = 0
object.forEach({ x: 1, y: 3 }, (v, k) => { forEachSum += v })
t.assert(forEachSum === 4)
t.describe('object.map')
t.assert(object.map({ x: 1, z: 5 }, (v, k) => v).reduce(math.add) === 6)
t.describe('object.length')
t.assert(object.length({}) === 0)
t.assert(object.length({ x: 1 }) === 1)
}
4 changes: 3 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import * as map from './map.test.js'
import * as eventloop from './eventloop.test.js'
import * as time from './time.test.js'
import * as pair from './pair.test.js'
import * as object from './object.test.js'

import { isBrowser, isNode } from './environment.js'

Expand All @@ -39,7 +40,8 @@ runTests({
map,
eventloop,
time,
pair
pair,
object
}).then(success => {
/* istanbul ignore next */
if (isNode) {
Expand Down
15 changes: 12 additions & 3 deletions testing.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,12 @@ const _compare = (a, b, path, message, customCompare) => {
if (object.length(a) !== object.length(b)) {
_failMessage(message, 'Objects have a different number of attributes', path)
}
object.forEach(a, (value, key) => _compare(value, b[key], `${path}["${key}"]`, message, customCompare))
object.forEach(a, (value, key) => {
if (!b.hasOwnProperty(key)) {
_failMessage(message, `Property ${path} does not exist on second argument`, path)
}
b.hasOwnProperty(key) && _compare(value, b[key], `${path}["${key}"]`, message, customCompare)
})
break
case Array:
if (a.length !== b.length) {
Expand All @@ -260,14 +265,18 @@ export const assert = (condition, message = null) => condition
? (message !== null && log.print(log.GREEN, log.BOLD, '√ ', log.UNBOLD, message))
: fail(message ? `Failed condition: ${message}` : 'Assertion failed')

export const fails = (f, message) => {
export const fails = f => {
let err = null
try {
f()
} catch (_err) {
err = _err
log.print(log.GREEN, '⇖ This Error was expected')
}
/* istanbul ignore if */
if (err === null) {
fail('Expected this to fail')
}
assert(err !== null, message)
}

/**
Expand Down
13 changes: 13 additions & 0 deletions testing.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@ export const testComparing = () => {
t.compare([1, 2], [1, 2], 'simple compare (array)')
t.compare({ a: [1, 2] }, { a: [1, 2] }, 'simple compare nested')

t.describe('The following errors are expected!')
t.fails(() => {
t.compare({ a: 4 }, { b: 5 }, 'childs are not equal')
})
t.fails(() => {
t.compare({ a: 4 }, { a: 5 }, 'childs are not equal')
})
t.fails(() => {
t.compare({ a: 4 }, null, 'childs are not equal')
})
t.fails(() => {
t.compare({ a: 4 }, [4], 'childs have different types')
})
Expand Down Expand Up @@ -40,6 +47,12 @@ export const testComparing = () => {
t.fails(() => {
t.compareObjects({ x: 3 }, { x: 1 }) // Compare different objects -- no message
})
t.fails(() => {
t.compare({ x: undefined }, { y: 1 }, 'compare correctly handles undefined')
})
t.fails(() => {
t.compareObjects({ x: undefined }, { y: 1 }, 'compare correctly handles undefined')
})
}

export const testFailing = () => {
Expand Down

0 comments on commit 6c9b113

Please sign in to comment.