Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests for Util Module #233

Merged
merged 12 commits into from
Jan 12, 2018
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does await null work? Wouldn't it just continue on immediately? Or is it similar to passing 0 to setTimeout, putting the subsequent code at the end of the execution queue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is some context, I hope this provides some help regarding the clarification of the use of await null. I am still searching for a better alternative. Hopefully the upgrade in jest might just resolve the issue.

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