import {
  filter_hash, set_from_array, make_memoized, make_one_memoized, compare, property_getter,
} from 'common/utilities'
import expect from 'expect'
import {spy} from 'sinon'

describe("filter_hash", () => {
  it("should be correct", () => {
    let filtered_hash = filter_hash({1: true, 2: false}, Boolean)
    expect(filtered_hash[1]).toEqual(true)
    expect(filtered_hash[2]).toNotExist()
    expect(Object.keys(filtered_hash).length).toEqual(1)
  })
})

describe("set_from_array", () => {
  it("should be correct", () => {
    let set = set_from_array([1, 2])
    expect(set[1]).toEqual(true)
    expect(set[2]).toEqual(true)
    expect(Object.keys(set).length).toEqual(2)
  })
})

describe("make_memoized", () => {
  it("should compute the same result", () => {
    let fun = (x, y) => x * y
    let memoized_fun = make_memoized(fun)
    expect(memoized_fun(3, 5)).toEqual(fun(3, 5))
    expect(memoized_fun(3, 5)).toEqual(fun(3, 5))
  })

  it("should call function only for new arguments", () => {
    let fun = spy((x, y) => x + y)
    let fun_with_specified_arity = (x, y) => fun(x, y)
    let memoized_fun = make_memoized(fun_with_specified_arity)
    memoized_fun(1, 2)
    memoized_fun(1, 2)
    expect(fun.callCount).toEqual(1)
    memoized_fun(1, 3)
    expect(fun.callCount).toEqual(2)
    memoized_fun(1, 2)
    expect(fun.callCount).toEqual(2)
  })
})

describe("make_one_memoized", () => {
  it("should call function only for a new argument", () => {
    let fun = spy((x) => "My favorite fruit is the " + x)
    let memoized_fun = make_one_memoized(fun)
    memoized_fun("apple")
    memoized_fun("apple")
    expect(fun.callCount).toEqual(1)
    memoized_fun("banana")
    expect(fun.callCount).toEqual(2)
    memoized_fun("apple")
    expect(fun.callCount).toEqual(2)
  })
})

describe('compare', () => {
  const compare_a = compare(property_getter('a'))
  expect(compare_a({a: 1}, {a: 2})).toEqual(-1)
  expect(compare_a({a: 2}, {a: 1})).toEqual(1)
  expect(compare(property_getter('a'), false)({a: 1}, {a: 2})).toEqual(1)
  expect(compare_a({a: 1}, {a: 1})).toEqual(0)
})
