import * as fc from 'fast-check'
import * as Enzyme from 'enzyme'
import * as Axe from 'jest-axe'
import * as React from 'react'
import TextInput from './TextInput'
import stringify from '../../services/stringify'
it('should exist', () => {
expect(TextInput).toBeDefined()
})
it('should be a component', () => {
expect(TextInput).toBeComponent()
})
it('should render without crashing given required props', () => {
expect(() => ).not.toThrow()
})
it('should render a base element to put interactive elements on', () => {
const wrapper = Enzyme.shallow()
expect(wrapper.find('label')).toHaveLength(1)
})
it('should render an indicator as additional description for the content', () => {
fc.assert(
fc.property(fc.string(1, 20), (indicator) => {
const wrapper = Enzyme.shallow()
expect(wrapper.find('div').childAt(2)).toHaveText(indicator)
}),
)
})
it('should render a hint for describing valid input values', () => {
fc.assert(
fc.property(fc.anything(), (label) => {
const wrapper = Enzyme.shallow()
const renderedLabel = stringify(label)
if (renderedLabel.length > 0) {
expect(wrapper.find('div').children()).toHaveLength(4)
expect(wrapper.find('div').childAt(3)).toHaveText(`(${renderedLabel})`)
} else {
expect(wrapper.find('div').children()).toHaveLength(2)
}
}),
)
})
it('should render a padding on the hint element when an indicator is present', () => {
const wrapper = Enzyme.shallow()
expect(wrapper.find('div').childAt(3)).not.toHaveStyle('padding', '1rem')
})
it('should render as half-opaque when disabled', () => {
const wrapper = Enzyme.shallow()
expect(wrapper.find('div')).toHaveStyle('opacity', 0.5)
})
describe.each`
multiline | inputWidth | tag
${false} | ${'100%'} | ${'input'}
${true} | ${undefined} | ${'textarea'}
`('on multiline (multiline=$multiline)', ({ tag: rawTag, multiline: rawMultiline, inputWidth: rawInputWidth }) => {
const tag = rawTag as string
const multiline = rawMultiline as boolean
const inputWidth = rawInputWidth as string
it('should render an element to input text on', () => {
const wrapper = Enzyme.shallow()
expect(wrapper.find('label').find(tag)).toHaveLength(1)
})
it('should render the rest of the passed props', () => {
const wrapper = Enzyme.shallow()
expect(
wrapper
.find('label')
.find(tag)
.prop('placeholder'),
).toBe('foo')
})
it('should render a padding on the input element when an indicator is present', () => {
const wrapper = Enzyme.shallow()
expect(
wrapper
.find('div')
.find(tag)
.prop('style')!.paddingRight,
).not.toBe('1rem')
})
describe('on being declared a block component', () => {
const BLOCK_DISPLAYS = ['block', 'grid', 'flex', 'table']
it('should render the base element fullwidth', () => {
const wrapper = Enzyme.shallow()
const { display } = wrapper.find('div').prop('style')!
expect(BLOCK_DISPLAYS).toContain(display)
})
it('should render the input fullwidth', () => {
const wrapper = Enzyme.shallow()
if (tag === 'textarea') {
expect(wrapper.find('label').find(tag)).not.toHaveStyle('width')
} else {
expect(wrapper.find('label').find(tag)).toHaveStyle('width', inputWidth)
}
})
it('should render the input as block element', () => {
const wrapper = Enzyme.shallow()
const { display } = wrapper
.find('label')
.find(tag)
.prop('style')!
expect(BLOCK_DISPLAYS).toContain(display)
})
})
})
describe('on aiding user input', () => {
it("should render a label to indicate the nature of the component's value", () => {
const wrapper = Enzyme.shallow()
expect(wrapper.find('label').find('span')).toHaveLength(1)
})
it('should render the label text', () => {
fc.assert(
fc.property(fc.anything(), (label) => {
const wrapper = Enzyme.shallow()
expect(wrapper.find('label').find('span')).toHaveText(stringify(label))
}),
{
numRuns: 300,
},
)
})
})
it('should guarantee minimal accessibility', () => {
fc.assert(
fc.asyncProperty(fc.string(1, 20), async (s) => {
const wrapper = Enzyme.mount()
const results = await Axe.axe(wrapper.getDOMNode())
expect(results).toHaveNoViolations()
}),
)
})