Skip to content

Commit

Permalink
Merge pull request #233 from reficul31/util-tests
Browse files Browse the repository at this point in the history
Tests for `src/util` modules
  • Loading branch information
poltak authored Jan 12, 2018
2 parents 8ad73ca + 5696ef7 commit 3bf329e
Show file tree
Hide file tree
Showing 13 changed files with 875 additions and 1 deletion.
18 changes: 18 additions & 0 deletions __mocks__/src/pouchdb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import PouchDB from 'pouchdb-core'

import PouchDBMemory from 'pouchdb-adapter-memory'
import mapreduce from 'pouchdb-mapreduce'
import replication from 'pouchdb-replication'

PouchDB.plugin(PouchDBMemory)
.plugin(mapreduce)
.plugin(replication)

const pouchdbOptions = {
name: 'testdb',
auto_compaction: true,
adapter: 'memory',
}

const db = PouchDB(pouchdbOptions)
export default db
28 changes: 28 additions & 0 deletions src/util/delay.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* eslint-env jest */

import delay from './delay'

jest.useFakeTimers()

describe('delay', () => {
test('should set a timer with the given delay', () => {
delay(1000)
expect(setTimeout.mock.calls.length).toBe(1)
expect(setTimeout.mock.calls[0][1]).toBe(1000)
})

test('should return a promise which resolves after the timer finishes', async () => {
const assertFunc = jest.fn()
delay(1000)
.then(assertFunc)
.catch(err => {})

await null
expect(assertFunc).not.toHaveBeenCalled()

jest.runAllTimers()

await null
expect(assertFunc).toHaveBeenCalled()
})
})
144 changes: 144 additions & 0 deletions src/util/event-to-promise.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/* eslint-env jest */

import 'core-js/fn/object/entries' // shim Object.entries
import pull from 'lodash/pull'

import eventToPromise from './event-to-promise'

class MockEvent {
constructor() {
this.listeners = []
}

addListener(listener) {
this.listeners.push(listener)
}

removeListener(listener) {
pull(this.listeners, listener)
}

trigger(...args) {
this.listeners.forEach(listener => listener.apply(null, args))
}
}

describe('eventToPromise', () => {
test('should return a promise', () => {
const promise = eventToPromise({})
expect(promise).toBeInstanceOf(Promise)
})

test('should listen and unlisten to the events', async () => {
// We try both passing multiple events (for resolveOpts) and a single event (for rejectOpts).
const resolveOpts = [
{ event: new MockEvent() },
{ event: new MockEvent() },
]
const rejectOpts = { event: new MockEvent() }
eventToPromise({
resolve: resolveOpts,
reject: rejectOpts,
})

// We use a bogus await statement to let any resolved promises invoke their callbacks.
// XXX Not sure if we can rely on this in every ES implementation.
await null
expect(resolveOpts[0].event.listeners.length).toBe(1)
expect(resolveOpts[1].event.listeners.length).toBe(1)
expect(rejectOpts.event.listeners.length).toBe(1)

// Trigger any of the events.
resolveOpts[1].event.trigger()

await null
expect(resolveOpts[0].event.listeners.length).toBe(0)
expect(resolveOpts[1].event.listeners.length).toBe(0)
expect(rejectOpts.event.listeners.length).toBe(0)
})

describe('should resolve with given value when a resolve-event occurs', () => {
const values = {
object: { someKey: 'someValue' },
function: () => ({ someKey: 'someValue' }),
}
Object.entries(values).forEach(([type, value]) => {
test(`when value is a: ${type}`, async () => {
const resolveOpts = { event: new MockEvent(), value }
const resolveHandler = jest.fn()
eventToPromise({
resolve: resolveOpts,
})
.then(resolveHandler)
.catch()

await null
expect(resolveHandler).not.toBeCalled()

resolveOpts.event.trigger()

await null
expect(resolveHandler).toBeCalledWith({ someKey: 'someValue' })
})
})
})

const reasons = {
string: 'something',
function: () => 'something else',
object: { someKey: 'something' },
}
describe('should reject with Error(string) if a reject-event occurs', () => {
Object.entries(reasons).forEach(([type, reason]) => {
test(`when reason is a: ${type}`, async () => {
const rejectOpts = {
event: new MockEvent(),
reason,
}
const rejectHandler = jest.fn()
eventToPromise({
reject: rejectOpts,
}).catch(rejectHandler)

await null
expect(rejectHandler).not.toBeCalled()

rejectOpts.event.trigger()

await null
expect(rejectHandler).toBeCalled()
const error = rejectHandler.mock.calls[0][0]
expect(error).toBeInstanceOf(Error)
expect(error.message).toMatch(/.*something.*/)
})
})
})

test('should apply filter to events', async () => {
const resolveOpts = {
event: new MockEvent(),
filter: jest.fn(),
}
const resolveHandler = jest.fn()
eventToPromise({
resolve: resolveOpts,
})
.then(resolveHandler)
.catch()

await null
expect(resolveHandler).not.toBeCalled()

resolveOpts.filter.mockReturnValueOnce(false)
resolveOpts.event.trigger()

await null
expect(resolveHandler).not.toBeCalled()

resolveOpts.filter.mockReturnValueOnce(true)
resolveOpts.event.trigger()

await null
expect(resolveHandler).toBeCalled()
})
})
109 changes: 109 additions & 0 deletions src/util/make-range-transform.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* eslint-env jest */

import {
makeRangeTransform,
makeNonlinearTransform,
} from './make-range-transform'

describe('makeRangeTransform', () => {
test('should work for basic cases', () => {
const transformFunction = makeRangeTransform({
domain: [66, 100],
range: [9, 200],
})
expect(transformFunction(79)).toBeCloseTo(82.029, 2)
expect(transformFunction(43)).toBeCloseTo(-120.205, 2)
expect(transformFunction(170)).toBeCloseTo(593.235, 2)
})

test('should clamp its outputs with clampOutput true', () => {
const transformFunction = makeRangeTransform({
domain: [93, 117],
range: [3, 10],
clampOutput: true,
})
expect(transformFunction(99)).toBeCloseTo(4.75, 2)
expect(transformFunction(83)).toBe(3)
expect(transformFunction(150)).toBe(10)
})

test('should work with descending domain and/or range', () => {
const transformFunction1 = makeRangeTransform({
domain: [100, 0],
range: [0, 10],
})
expect(transformFunction1(80)).toBe(2)
expect(transformFunction1(-40)).toBe(14)
expect(transformFunction1(120)).toBe(-2)
const transformFunction2 = makeRangeTransform({
domain: [0, 100],
range: [10, 0],
})
expect(transformFunction2(80)).toBe(2)
expect(transformFunction2(-40)).toBe(14)
expect(transformFunction2(120)).toBe(-2)
const transformFunction3 = makeRangeTransform({
domain: [100, 0],
range: [10, 0],
})
expect(transformFunction3(80)).toBe(8)
expect(transformFunction3(-40)).toBe(-4)
expect(transformFunction3(120)).toBe(12)
})

test('should work with descending domain and/or range with clamping', () => {
const transformFunction1 = makeRangeTransform({
domain: [100, 0],
range: [0, 10],
clampOutput: true,
})
expect(transformFunction1(80)).toBe(2)
expect(transformFunction1(-40)).toBe(10)
expect(transformFunction1(120)).toBe(0)
const transformFunction2 = makeRangeTransform({
domain: [0, 100],
range: [10, 0],
clampOutput: true,
})
expect(transformFunction2(80)).toBe(10)
expect(transformFunction2(-40)).toBe(10)
expect(transformFunction2(120)).toBe(10)
const transformFunction3 = makeRangeTransform({
domain: [100, 0],
range: [10, 0],
clampOutput: true,
})
expect(transformFunction3(80)).toBe(10)
expect(transformFunction3(-40)).toBe(10)
expect(transformFunction3(120)).toBe(10)
})
})

describe('makeNonlinearTransform', () => {
test('should work for basic cases', () => {
const transformFunction = makeNonlinearTransform({
domain: [5, 5603],
range: [0, 100],
nonlinearity: Math.log,
})
expect(transformFunction(5)).toBe(0)
expect(transformFunction(5603)).toBe(100)
expect(transformFunction(3)).toBeCloseTo(-7.275, 2)
expect(transformFunction(1997)).toBeCloseTo(85.3074, 2)
expect(transformFunction(6000)).toBeCloseTo(100.974, 2)
})

test('should clamp its outputs with clampOutput true', () => {
const transformFunction = makeNonlinearTransform({
domain: [5, 5603],
range: [0, 100],
clampOutput: true,
nonlinearity: Math.log,
})
expect(transformFunction(5)).toBe(0)
expect(transformFunction(5603)).toBe(100)
expect(transformFunction(3)).toBe(0)
expect(transformFunction(1997)).toBeCloseTo(85.3074, 2)
expect(transformFunction(6000)).toBe(100)
})
})
52 changes: 52 additions & 0 deletions src/util/nice-time.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* eslint-env jest */

import niceTime from './nice-time'

describe('niceTime', () => {
test('should return now for timeperiod of less than 90 seconds', () => {
const date = new Date()
expect(niceTime(date)).toBe('now')
})

test('should return minutes for timeperiod of less than 600 seconds', () => {
const date = new Date(2016, 7, 2, 14, 25)
const now = new Date(2016, 7, 2, 14, 45)
expect(niceTime(date, { now })).toBe('20 minutes ago')
})

test('should return timeperiod stamp for timeperiod less than 24 hours', () => {
const date = new Date(2016, 7, 2, 14, 25)
const now = new Date(2016, 7, 2, 18, 55)
expect(niceTime(date, { now })).toBe('14:25')
})

test('should return the timeperiod stamp and the day for timeperiod less than 24 hours but not on the same day', () => {
const date = new Date(2016, 7, 2, 14, 25)
const now = new Date(2016, 7, 3, 10, 55)
expect(niceTime(date, { now })).toBe('Yesterday 14:25')
})

test('should return the day and timestamp for timeperiod less than 3 days', () => {
const date = new Date(2016, 7, 2, 14, 25)
const now = new Date(2016, 7, 4, 18, 55)
expect(niceTime(date, { now })).toBe('Tue 14:25')
})

test('should return the date and the month for timeperiod in the same year', () => {
const date = new Date(2016, 7, 2, 14, 25)
const now = new Date(2016, 9, 2, 18, 55)
expect(niceTime(date, { now })).toBe('2 Aug')
})

test('should return the date, month and year for timeperiod not in the same year', () => {
const date = new Date(2016, 7, 2, 14, 25)
const now = new Date(2017, 7, 2, 18, 55)
expect(niceTime(date, { now })).toBe('2 Aug 2016')
})

test('should return the placeholder for invalid date', () => {
const date = new Date(2016, 7, 3, 14, 25)
const now = new Date(2016, 7, 2, 18, 55)
expect(niceTime(date, { now })).toBe('soon?!')
})
})
Loading

0 comments on commit 3bf329e

Please sign in to comment.