accessibility.spec.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import selectEvent from 'react-select-event';
  2. import {
  3. fireEvent,
  4. render,
  5. screen,
  6. userEvent,
  7. within,
  8. } from 'sentry-test/reactTestingLibrary';
  9. import Form from 'sentry/components/forms/form';
  10. import FormModel from '../model';
  11. import BooleanField from './booleanField';
  12. import CheckboxField from './checkboxField';
  13. import EmailField from './emailField';
  14. import HiddenField from './hiddenField';
  15. import NumberField from './numberField';
  16. import RadioField from './radioField';
  17. import RangeField from './rangeField';
  18. import SecretField from './secretField';
  19. import SelectField from './selectField';
  20. import SeparatorField from './separatorField';
  21. import TextareaField from './textareaField';
  22. import TextField from './textField';
  23. describe('Field accessibility', function () {
  24. it('has appropriate aria attributes on all fields', async function () {
  25. // TODO(epurkhiser): The following fields are sill missing accessibility
  26. // check tests:
  27. //
  28. // - ChoiceMapper
  29. // - ProjectMapperField
  30. // - SentryProjectSelectorField
  31. // - TableField
  32. // - DatePickerField
  33. // - DateTimeField
  34. // - FileField
  35. // TODO(epurkhiser): It would be really nice if we could enforce that every
  36. // field that exists in `components/forms/fields/*` has a proper
  37. // accessibility test here.
  38. const model = new FormModel();
  39. render(
  40. <Form model={model}>
  41. <SeparatorField />
  42. <HiddenField name="hidden" defaultValue="itsHidden" />
  43. <TextField label="My Text Input" help="This is a text input" name="myTextInput" />
  44. <NumberField
  45. label="My Number Input"
  46. help="This is a number input"
  47. name="myNumberInput"
  48. />
  49. <EmailField
  50. label="My Email Input"
  51. help="This is a email input"
  52. name="myEmailInput"
  53. />
  54. <SecretField
  55. label="My Password"
  56. help="This is a password input"
  57. name="mySecretInput"
  58. />
  59. <TextareaField
  60. label="My Textarea"
  61. help="This is a text area input"
  62. name="myTextarea"
  63. />
  64. <CheckboxField
  65. label="My Checkbox"
  66. help="This is a checkbox (not a switch)"
  67. name="myCheckbox"
  68. />
  69. <BooleanField
  70. label="My Boolean"
  71. help="This is a boolean switch toggle"
  72. name="myBoolean"
  73. />
  74. <RadioField
  75. label="My Radios"
  76. choices={[
  77. ['thing_1', 'Thing 1', 'Thing 1 description'],
  78. ['thing_2', 'Thing 2', 'Thing 2 description'],
  79. ]}
  80. help="This is a radio set field"
  81. name="myRadios"
  82. />
  83. <RangeField
  84. label="My Range Slider"
  85. min={0}
  86. max={100}
  87. step={10}
  88. defaultValue={10}
  89. help="This is a range slider"
  90. name="myRangeSlider"
  91. />
  92. <SelectField
  93. label="My Select"
  94. options={[
  95. {value: 'item1', label: 'Item 1'},
  96. {value: 'item2', label: 'Item 2'},
  97. ]}
  98. help="This is a select field field"
  99. name="mySelectbox"
  100. />
  101. </Form>
  102. );
  103. // Separator field
  104. expect(screen.getByRole('separator')).toBeInTheDocument();
  105. // Hidden field
  106. expect(model.getValue('hidden')).toBe('itsHidden');
  107. // Text Input
  108. const textInput = screen.getByRole('textbox', {name: 'My Text Input'});
  109. userEvent.type(textInput, 'testing');
  110. expect(textInput).toHaveValue('testing');
  111. expect(model.getValue('myTextInput')).toBe('testing');
  112. // Number field
  113. const numberInput = screen.getByRole('spinbutton', {name: 'My Number Input'});
  114. userEvent.type(numberInput, '1');
  115. expect(numberInput).toHaveValue(1);
  116. expect(model.getValue('myNumberInput')).toBe('1');
  117. // Password field
  118. const passwordField = screen.getByRole('textbox', {name: 'My Password'});
  119. userEvent.type(passwordField, 'hunter2');
  120. expect(passwordField).toHaveValue('hunter2');
  121. expect(model.getValue('mySecretInput')).toBe('hunter2');
  122. // Number field
  123. const emailInput = screen.getByRole('textbox', {name: 'My Email Input'});
  124. userEvent.type(emailInput, 'evan@p.com');
  125. expect(emailInput).toHaveValue('evan@p.com');
  126. expect(model.getValue('myEmailInput')).toBe('evan@p.com');
  127. // Textarea field
  128. const textarea = screen.getByRole('textbox', {name: 'My Textarea'});
  129. userEvent.type(textarea, 'evan@p.com');
  130. expect(textarea).toHaveValue('evan@p.com');
  131. expect(model.getValue('myEmailInput')).toBe('evan@p.com');
  132. // Checkbox field
  133. const checkbox = screen.getByRole('checkbox', {name: 'My Checkbox'});
  134. userEvent.click(checkbox);
  135. expect(checkbox).toBeChecked();
  136. expect(model.getValue('myCheckbox')).toBe(true);
  137. // Boolean switch field
  138. const boolean = screen.getByRole('checkbox', {name: 'My Boolean'});
  139. userEvent.click(boolean);
  140. expect(boolean).toBeChecked();
  141. expect(model.getValue('myBoolean')).toBe(true);
  142. // Radio group
  143. const radiogroup = screen.getByRole('radiogroup', {name: 'My Radios'});
  144. const radioItem1 = within(radiogroup).getByRole('radio', {name: 'Thing 1'});
  145. const radioItem2 = within(radiogroup).getByRole('radio', {name: 'Thing 2'});
  146. userEvent.click(radioItem1);
  147. expect(radioItem1).toBeChecked();
  148. expect(radioItem2).not.toBeChecked();
  149. expect(model.getValue('myRadios')).toBe('thing_1');
  150. userEvent.click(radioItem2);
  151. expect(radioItem1).not.toBeChecked();
  152. expect(radioItem2).toBeChecked();
  153. expect(model.getValue('myRadios')).toBe('thing_2');
  154. // Range slider field
  155. //
  156. // XXX(epurkhiser): slider inputs are not currently supported by userEvent,
  157. // fireEvent.change must be used
  158. const rangeSlider = screen.getByRole('slider', {name: 'My Range Slider'});
  159. fireEvent.change(rangeSlider, {target: {value: '20'}});
  160. expect(rangeSlider).toHaveValue('20');
  161. expect(model.getValue('myRangeSlider')).toBe(20);
  162. // Select field
  163. //
  164. // The input is a textbox, and we can test with `selectEvent`
  165. const select = screen.getByRole('textbox', {name: 'My Select'});
  166. await selectEvent.select(select, ['Item 1']);
  167. expect(model.getValue('mySelectbox')).toBe('item1');
  168. await selectEvent.select(select, ['Item 2']);
  169. expect(model.getValue('mySelectbox')).toBe('item2');
  170. });
  171. });