import {
  testContext,
  testHook,
  testRenderProp,
} from '../../__tests__/helpers/state'
import {
  ListNavigation,
  ListNavigationProvider,
  useListNavigation,
  useListNavigationContext,
} from '../ListNavigation'

const validateAPI = (api) => {
  expect(api.index).toEqual(0)
  expect(api.set).toBeInstanceOf(Function)
  expect(api.increment).toBeInstanceOf(Function)
  expect(api.decrement).toBeInstanceOf(Function)
  expect(api.clear).toBeInstanceOf(Function)
}

const apiTest = {
  test: 'api',
  config: {},
  callback: validateAPI,
}

const configTest = {
  test: 'config',
  config: { initialIndex: 3 },
  callback: ({ index }) => expect(index).toEqual(3),
}

const spy = jest.spyOn(global.console, 'warn')
beforeEach(() => {
  spy.mockReset()
})

describe('ListNavigation', () => {
  testHook(useListNavigation, [
    apiTest,
    configTest,
    {
      test: 'mutations',
      config: { size: 5, initialIndex: -1 },
      mutations: [
        ['set', 3, ['index', 'toBe', 3]],
        ['increment', null, ['index', 'toBe', 4]],
        ['decrement', null, ['index', 'toBe', 3]],
        ['clear', null, ['index', 'toBe', 0]],
        ['set', 3, ['index', 'toBe', 3]],
        ['decrementBy', 2, ['index', 'toBe', 1]],
        ['incrementBy', 3, ['index', 'toBe', 4]],
        ['reset', null, ['index', 'toBe', 0]],
      ],
    },
    {
      test: 'is circular',
      config: { circular: true, initialIndex: 4, size: 5 },
      mutations: [
        ['increment', null, ['index', 'toBe', 0]],
        ['decrement', null, ['index', 'toBe', 4]],
      ],
    },
    {
      test: 'is not circular, does not increment past size',
      config: { circular: false, initialIndex: 5, size: 6 },
      mutations: [['increment', null, ['index', 'toBe', 5]]],
    },
    {
      test: 'is not circular, does not have a size, can decrement',
      config: { circular: false, initialIndex: 100, size: 200 },
      mutations: [['decrement', null, ['index', 'toBe', 99]]],
    },
    {
      test: 'is not circular, does not have a size, can increment',
      config: { circular: false, initialIndex: 100, size: 200 },
      mutations: [['increment', null, ['index', 'toBe', 101]]],
    },
  ])

  testRenderProp(ListNavigation, 'listNavigation', [apiTest, configTest])

  testContext(ListNavigationProvider, useListNavigationContext, [
    apiTest,
    configTest,
    {
      test: 'missing provider',
      config: {},
      injectProvider: false,
      callback: (context, { spy }) => {
        expect(context.index).toBe(-1)
        context.set()
        context.increment()
        context.decrement()
        context.clear()
        context.reset()
        expect(spy).toBeCalledTimes(5)
      },
    },
  ])
})
