it('render billboard after loading', (done) => {
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   setTimeout(() => {
     expect(wrapper.find('Billboard')).toHaveLength(1)
     done()
   }, 1)
 })
 it('renders two ratings that are deletable', () => {
   const promise = Promise.resolve({
     status: 200,
     data: {ratings: [
       {
         description: 'Great',
         points: 10,
         color: '0000ff',
         mastery: true
       },
       {
         description: 'Poor',
         points: 0,
         color: 'ff0000',
         mastery: false
       }
     ]}
   })
   const spy = jest.spyOn(axios,'get').mockImplementation(() => promise)
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   return promise.then(() => {
       spy.mockRestore()
       expect(wrapper.find('ProficiencyRating')).toHaveLength(2)
       expect(wrapper.find('ProficiencyRating').first().prop('disableDelete')).toBeFalsy()
       expect(wrapper.find('ProficiencyRating').last().prop('disableDelete')).toBeFalsy()
     }
   )
 })
 it('renders five ratings', (done) => {
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   setTimeout(() => {
     wrapper.instance().removeBillboard()
     expect(wrapper.find('ProficiencyRating')).toHaveLength(5)
     done()
   }, 1)
 })
 it('sets state to lastUnknown if there is no last link', () => {
   const props = getProps()
   const wrapper = mount(<SearchMessage {...props} />)
   delete props.collection.links.last
   props.collection.links.next = {url: 'next', page: '2'}
   wrapper.setProps(props)
   expect(wrapper.instance().isLastPageUnknown()).toBe(true)
 })
 it('shows the loading spinner on the page that is becoming current', () => {
   const props = getProps()
   const wrapper = mount(<SearchMessage {...props} />)
   wrapper.setProps({}) // Make sure it triggers componentWillReceiveProps
   wrapper.instance().handleSetPage(6)
   const buttons = wrapper.find('PaginationButton').map(x => x.text())
   expect(buttons).toEqual(['1', '5', 'Loading...', '7', '8', '9', '10'])
 })
 it('clicking button adds rating', (done) => {
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   setTimeout(() => {
     wrapper.instance().removeBillboard()
     wrapper.findWhere(n => n.prop('variant') === 'circle-primary').simulate('click')
     expect(wrapper.find('ProficiencyRating')).toHaveLength(6)
     done()
   }, 1)
 })
 it('setting negative points sets error', (done) => {
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   setTimeout(() => {
     wrapper.instance().removeBillboard()
     wrapper.instance().handlePointsChange(0)("-1")
     wrapper.find('Button').last().simulate('click')
     expect(wrapper.find('ProficiencyRating').first().prop('pointsError')).toBe('Negative points')
     done()
   }, 1)
 })
 it('setting blank description sets error', (done) => {
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   setTimeout(() => {
     wrapper.instance().removeBillboard()
     wrapper.instance().handleDescriptionChange(0)("")
     wrapper.find('Button').last().simulate('click')
     expect(wrapper.find('ProficiencyRating').first().prop('descriptionError')).toBe('Missing required description')
     done()
   }, 1)
 })
 it('sends POST on submit', (done) => {
   const postSpy = jest.spyOn(axios,'post').mockImplementation(() => Promise.resolve({status: 200}))
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   setTimeout(() => {
     wrapper.instance().removeBillboard()
     wrapper.find('Button').last().simulate('click')
     expect(axios.post).toHaveBeenCalledTimes(1)
     postSpy.mockRestore()
     done()
   }, 1)
 })
 it('clicking add rating button flashes SR message', (done) => {
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   const flashMock = jest.spyOn($, 'screenReaderFlashMessage')
   setTimeout(() => {
     wrapper.instance().removeBillboard()
     wrapper.findWhere(n => n.prop('variant') === 'circle-primary').simulate('click')
     expect(flashMock).toHaveBeenCalledTimes(1)
     flashMock.mockRestore()
     done()
   }, 1)
 })
 it('handling delete rating removes rating and flashes SR message', (done) => {
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   const flashMock = jest.spyOn($, 'screenReaderFlashMessage')
   setTimeout(() => {
     wrapper.instance().removeBillboard()
     wrapper.instance().handleDelete(1)()
     expect(wrapper.find('ProficiencyRating')).toHaveLength(4)
     expect(flashMock).toHaveBeenCalledTimes(1)
     flashMock.mockRestore()
     done()
   }, 1)
 })
 it('sets focusField on mastery on first rating only', (done) => {
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   setTimeout(() => {
     wrapper.instance().removeBillboard()
     expect(wrapper.find('ProficiencyRating').at(0).prop('focusField')).toBe('mastery')
     expect(wrapper.find('ProficiencyRating').at(1).prop('focusField')).toBeNull()
     expect(wrapper.find('ProficiencyRating').at(2).prop('focusField')).toBeNull()
     expect(wrapper.find('ProficiencyRating').at(3).prop('focusField')).toBeNull()
     expect(wrapper.find('ProficiencyRating').at(4).prop('focusField')).toBeNull()
     done()
   }, 1)
 })
  it('can handle lots of pages', () => {
    const props = getProps()
    props.collection.links.last.page = '1000'
    const wrapper = mount(<SearchMessage {...props} />)

    const buttons2 = wrapper.find('PaginationButton').map(x => x.text())
    expect(buttons2).toEqual(['1', '4', '5', '6', '7', '8', '1,000'])

    wrapper.find('button[aria-label="Page 1,000"]').simulate('click')
    wrapper.setProps({}) // Make sure it triggers componentWillReceiveProps

    const buttons = wrapper.find('PaginationButton').map(x => x.text())
    expect(buttons).toEqual(['1', '4', '5', '6', '7', '8', '1,000'])
  })
 it('renders one rating that is not deletable', () => {
   const promise = Promise.resolve({
     status: 200,
     data: {ratings: [
       {
         description: 'Uno',
         points: 1,
         color: '0000ff',
         mastery: true
       }
     ]}
   })
   const spy = jest.spyOn(axios,'get').mockImplementation(() => promise)
   const wrapper = mount(<ProficiencyTable {...defaultProps()}/>)
   return promise.then(() => {
       spy.mockRestore()
       expect(wrapper.find('ProficiencyRating')).toHaveLength(1)
       expect(wrapper.find('ProficiencyRating').first().prop('disableDelete')).toBeTruthy()
     }
   )
 })
it('increasing rating points generates errors', () => {
  const wrapper = shallow(<ProficiencyTable {...defaultProps()}/>)
  wrapper.instance().handlePointsChange(1)("100")
  expect(wrapper.instance().checkForErrors()).toBe(true)
})
 it('renders loading at startup', () => {
   const wrapper = shallow(<ProficiencyTable {...defaultProps()}/>)
   expect(wrapper.find('Spinner')).toHaveLength(1)
 })
 it('renders the ProficiencyRating component', () => {
   const wrapper = shallow(<ProficiencyTable {...defaultProps()}/>)
   expect(wrapper.debug()).toMatchSnapshot()
 })
it('negative rating points leaves state invalid', () => {
  const wrapper = shallow(<ProficiencyTable {...defaultProps()}/>)
  wrapper.instance().handlePointsChange(0)("-1")
  expect(wrapper.instance().isStateValid()).toBe(false)
})
it('empty rating description generates errors', () => {
  const wrapper = shallow(<ProficiencyTable {...defaultProps()}/>)
  wrapper.instance().handleDescriptionChange(0)("")
  expect(wrapper.instance().checkForErrors()).toBe(true)
})
it('shows spinner when loading', () => {
  const props = getProps()
  props.collection.loading = true
  const wrapper = mount(<SearchMessage {...props} />)
  expect(wrapper.find('Spinner').exists()).toBe(true)
})