import React from 'react'

import SelectLocator from '@instructure/ui-forms/lib/components/Select/locator'
import TagLocator from '@instructure/ui-elements/lib/components/Tag/locator'
import { mount, stub, within } from '@instructure/ui-test-utils'

import TagSelect from '../index'

describe('TagSelect', () => {
  let onChangeStub, onInputChangeStub, props

  beforeEach(() => {
    onChangeStub = stub()
    onInputChangeStub = stub()
    props = {
      noMatchText: '404 TAG NOT FOUND',
      onChange: onChangeStub,
      onInputChange: onInputChangeStub
    }
  })

  it('should render select label', async () => {
    const subject = await mount(<TagSelect {...props} />)

    const tagSelect = within(subject.getDOMNode())
    expect(tagSelect.getTextContent()).to.include('Tags and Metadata')
  })

  it('should render one selected option', async () => {
    const subject = await mount(
      <TagSelect
        {...props}
        tags={[
          { id: '1', value: 'waldo' }
        ]}
      />
    )

    const tagSelect = within(subject.getDOMNode())
    expect(tagSelect.getTextContent()).to.include('waldo')
  })

  it('should call onChange when a tag is removed', async () => {
    await mount(
      <TagSelect
        {...props}
        tags={[
          { id: '1', value: 'waldo' }
        ]}
      />
    )

    const tag = await TagLocator.find()
    await tag.click()

    expect(onChangeStub).to.be.called()
  })

  it('display empty option when entering text', async () => {
    await mount(<TagSelect {...props} />)

    const select = await SelectLocator.find()
    const input = await select.findInput()
    await input.click()

    const optionsList = await select.findOptionsList()
    expect(optionsList.getTextContent()).to.include('404 TAG NOT FOUND')
  })

  it('offers tag creation when text is entered', async () => {
    await mount(
      <TagSelect
        {...props}
        allowNewTags
      />
    )

    const select = await SelectLocator.find()
    const input = await select.findInput()
    await input.click()
    await input.typeIn('hi')

    const options = await select.findAllOptions()
    const createOption = options[0]
    const text = createOption.getTextContent()
    expect(text).to.include('Create new tag: hi')

    await createOption.click()
    expect(onChangeStub).to.be.calledWith([{ value: 'hi' }])
  })

  it('does not offer to create a tag that is already selected', async () => {
    await mount(
      <TagSelect
        {...props}
        allowNewTags
        tags={[
          { value: 'waldo' }
        ]}
      />
    )

    const select = await SelectLocator.find()
    const input = await select.findInput()
    await input.click()
    await input.typeIn('waldo')

    const options = await select.findAllOptions()
    const emptyOption = options[0]
    expect(emptyOption.getTextContent()).to.include('Tag already selected: waldo')

    await emptyOption.click()
    expect(onChangeStub).to.not.be.called()
  })

  it('offers all tag suggestions', async () => {
    await mount(
      <TagSelect
        {...props}
        tagSuggestions={[
          { id: '1', value: 'tag-1' },
          { id: '2', value: 'tag-2' }
        ]}
      />
    )

    const select = await SelectLocator.find()
    const input = await select.findInput()
    await input.click()

    const optionsList = await select.findOptionsList()
    const text = optionsList.getTextContent()
    expect(text).to.include('tag-1')
    expect(text).to.include('tag-2')
  })

  it('does not offer tag creation on suggested tags', async () => {
    const subject = await mount(
      <TagSelect
        {...props}
        allowNewTags
        tagSuggestions={[
          { id: '1', value: 'tag-1' }
        ]}
      />
    )

    const select = await SelectLocator.find()
    const input = await select.findInput()
    await input.click()

    const tagSelect = within(subject.getDOMNode())
    expect(tagSelect.getTextContent()).to.not.include('Create new tag')
  })

  it('does not remove existing tag with text matching the tag id', async () => {
    const subject = await mount(
      <TagSelect
        {...props}
        tags={[
          { value: 'waldo' }
        ]}
        tagSuggestions={[
          { id: '1', value: 'tag-1' }
        ]}
      />
    )

    const tagSelect = within(subject.getDOMNode())
    expect(tagSelect.getTextContent()).to.include('waldo')
  })

  it('should meet a11y standards', async () => {
    const subject = await mount(<TagSelect {...props} />)

    const tagSelect = within(subject.getDOMNode())
    expect(await tagSelect.accessible()).to.be.true()
  })
})
