Common front-end components for Web using the Tesseract design system, written for React. https://make.modal.sh/tesseract/web/react/common
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TextInput.test.tsx 4.8 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import * as fc from 'fast-check'
  2. import * as Enzyme from 'enzyme'
  3. import * as Axe from 'jest-axe'
  4. import * as React from 'react'
  5. import TextInput from './TextInput'
  6. import stringify from '../../services/stringify'
  7. it('should exist', () => {
  8. expect(TextInput).toBeDefined()
  9. })
  10. it('should be a component', () => {
  11. expect(TextInput).toBeComponent()
  12. })
  13. it('should render without crashing given required props', () => {
  14. expect(() => <TextInput />).not.toThrow()
  15. })
  16. it('should render a base element to put interactive elements on', () => {
  17. const wrapper = Enzyme.shallow(<TextInput />)
  18. expect(wrapper.find('label')).toHaveLength(1)
  19. })
  20. it('should render an indicator as additional description for the content', () => {
  21. fc.assert(
  22. fc.property(fc.string(1, 20), (indicator) => {
  23. const wrapper = Enzyme.shallow(<TextInput indicator={indicator} />)
  24. expect(wrapper.find('div').childAt(2)).toHaveText(indicator)
  25. }),
  26. )
  27. })
  28. it('should render a hint for describing valid input values', () => {
  29. fc.assert(
  30. fc.property(fc.anything(), (label) => {
  31. const wrapper = Enzyme.shallow(<TextInput hint={label} />)
  32. const renderedLabel = stringify(label)
  33. if (renderedLabel.length > 0) {
  34. expect(wrapper.find('div').children()).toHaveLength(4)
  35. expect(wrapper.find('div').childAt(3)).toHaveText(`(${renderedLabel})`)
  36. } else {
  37. expect(wrapper.find('div').children()).toHaveLength(2)
  38. }
  39. }),
  40. )
  41. })
  42. it('should render a padding on the hint element when an indicator is present', () => {
  43. const wrapper = Enzyme.shallow(<TextInput hint="foo" indicator="foobar" />)
  44. expect(wrapper.find('div').childAt(3)).not.toHaveStyle('padding', '1rem')
  45. })
  46. it('should render as half-opaque when disabled', () => {
  47. const wrapper = Enzyme.shallow(<TextInput disabled />)
  48. expect(wrapper.find('div')).toHaveStyle('opacity', 0.5)
  49. })
  50. describe.each`
  51. multiline | inputWidth | tag
  52. ${false} | ${'100%'} | ${'input'}
  53. ${true} | ${undefined} | ${'textarea'}
  54. `('on multiline (multiline=$multiline)', ({ tag: rawTag, multiline: rawMultiline, inputWidth: rawInputWidth }) => {
  55. const tag = rawTag as string
  56. const multiline = rawMultiline as boolean
  57. const inputWidth = rawInputWidth as string
  58. it('should render an element to input text on', () => {
  59. const wrapper = Enzyme.shallow(<TextInput multiline={multiline} />)
  60. expect(wrapper.find('label').find(tag)).toHaveLength(1)
  61. })
  62. it('should render the rest of the passed props', () => {
  63. const wrapper = Enzyme.shallow(<TextInput multiline={multiline} placeholder="foo" />)
  64. expect(
  65. wrapper
  66. .find('label')
  67. .find(tag)
  68. .prop('placeholder'),
  69. ).toBe('foo')
  70. })
  71. it('should render a padding on the input element when an indicator is present', () => {
  72. const wrapper = Enzyme.shallow(<TextInput multiline={multiline} indicator="foobar" />)
  73. expect(
  74. wrapper
  75. .find('div')
  76. .find(tag)
  77. .prop('style')!.paddingRight,
  78. ).not.toBe('1rem')
  79. })
  80. describe('on being declared a block component', () => {
  81. const BLOCK_DISPLAYS = ['block', 'grid', 'flex', 'table']
  82. it('should render the base element fullwidth', () => {
  83. const wrapper = Enzyme.shallow(<TextInput multiline={multiline} block />)
  84. const { display } = wrapper.find('div').prop('style')!
  85. expect(BLOCK_DISPLAYS).toContain(display)
  86. })
  87. it('should render the input fullwidth', () => {
  88. const wrapper = Enzyme.shallow(<TextInput multiline={multiline} block />)
  89. if (tag === 'textarea') {
  90. expect(wrapper.find('label').find(tag)).not.toHaveStyle('width')
  91. } else {
  92. expect(wrapper.find('label').find(tag)).toHaveStyle('width', inputWidth)
  93. }
  94. })
  95. it('should render the input as block element', () => {
  96. const wrapper = Enzyme.shallow(<TextInput multiline={multiline} block />)
  97. const { display } = wrapper
  98. .find('label')
  99. .find(tag)
  100. .prop('style')!
  101. expect(BLOCK_DISPLAYS).toContain(display)
  102. })
  103. })
  104. })
  105. describe('on aiding user input', () => {
  106. it("should render a label to indicate the nature of the component's value", () => {
  107. const wrapper = Enzyme.shallow(<TextInput label="foo" />)
  108. expect(wrapper.find('label').find('span')).toHaveLength(1)
  109. })
  110. it('should render the label text', () => {
  111. fc.assert(
  112. fc.property(fc.anything(), (label) => {
  113. const wrapper = Enzyme.shallow(<TextInput label={label} />)
  114. expect(wrapper.find('label').find('span')).toHaveText(stringify(label))
  115. }),
  116. {
  117. numRuns: 300,
  118. },
  119. )
  120. })
  121. })
  122. it('should guarantee minimal accessibility', () => {
  123. fc.assert(
  124. fc.asyncProperty(fc.string(1, 20), async (s) => {
  125. const wrapper = Enzyme.mount(<TextInput label={s} />)
  126. const results = await Axe.axe(wrapper.getDOMNode())
  127. expect(results).toHaveNoViolations()
  128. }),
  129. )
  130. })