import {
  testContext,
  testHook,
  testRenderProp,
} from '../../__tests__/helpers/state'
import {
  InjectedScript,
  InjectedScriptProvider,
  useInjectedScript,
  useInjectedScriptContext,
} from '../InjectedScript'

const validateAPI = (api) => {
  expect(api.isLoaded).toEqual(false)
  expect(api.setLoaded).toBeInstanceOf(Function)
}

const apiTest = {
  test: 'api',
  config: {
    id: 'foo',
    src: 'bar',
  },
  callback: validateAPI,
}

const configTest = {
  test: 'config',
  config: {
    id: 'foo',
    src: 'bar',
  },
  callback: ({ id, src }) => {
    expect(id).toEqual(id)
    expect(src).toEqual(src)
  },
}

beforeEach(() => {
  document.head.innerHTML = ''
})

describe('InjectedScript', () => {
  testHook(useInjectedScript, [
    apiTest,
    configTest,
    {
      test: 'mutations',
      config: {},
      mutations: [
        ['setLoaded', true, ['isLoaded', 'toBe', true]],
        ['setLoaded', false, ['isLoaded', 'toBe', false]],
      ],
    },
  ])

  testRenderProp(InjectedScript, 'injectedScript', [apiTest, configTest])

  testContext(InjectedScriptProvider, useInjectedScriptContext, [
    apiTest,
    configTest,
    {
      test: 'missing provider',
      config: {},
      injectProvider: false,
      callback: (context, { spy }) => {
        spy.mockImplementation(() => {})

        expect(context.isLoaded).toBe(false)
        context.setLoaded()
        expect(spy).toBeCalledTimes(1)
        expect(spy).toBeCalledWith(
          'Could not call `setLoaded`, please wrap your component in a `<InjectedScriptProvider>`'
        )

        spy.mockRestore()
      },
    },
  ])
})
