OptionPicker.test.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { render, screen } from '@testing-library/react';
  2. import userEvent from '@testing-library/user-event';
  3. import React from 'react';
  4. import { Provider } from 'react-redux';
  5. import { LoadingState } from '@grafana/data';
  6. import { selectors } from '@grafana/e2e-selectors';
  7. import { queryBuilder } from '../../shared/testing/builders';
  8. import { getPreloadedState } from '../../state/helpers';
  9. import { QueryVariableModel, VariableWithMultiSupport, VariableWithOptions } from '../../types';
  10. import { VariablePickerProps } from '../types';
  11. import { optionPickerFactory } from './OptionsPicker';
  12. import { initialOptionPickerState, OptionsPickerState } from './reducer';
  13. interface Args {
  14. pickerState?: Partial<OptionsPickerState>;
  15. variable?: Partial<QueryVariableModel>;
  16. }
  17. const defaultVariable = queryBuilder()
  18. .withId('query0')
  19. .withRootStateKey('key')
  20. .withName('query0')
  21. .withMulti()
  22. .withCurrent(['A', 'C'])
  23. .withOptions('A', 'B', 'C')
  24. .build();
  25. function setupTestContext({ pickerState = {}, variable = {} }: Args = {}) {
  26. const v = {
  27. ...defaultVariable,
  28. ...variable,
  29. };
  30. const onVariableChange = jest.fn();
  31. const props: VariablePickerProps<VariableWithMultiSupport | VariableWithOptions> = {
  32. variable: v,
  33. onVariableChange,
  34. };
  35. const Picker = optionPickerFactory();
  36. const optionsPicker: OptionsPickerState = { ...initialOptionPickerState, ...pickerState };
  37. const dispatch = jest.fn();
  38. const subscribe = jest.fn();
  39. const templatingState = {
  40. variables: {
  41. [v.id]: { ...v },
  42. },
  43. optionsPicker,
  44. };
  45. const getState = jest.fn().mockReturnValue(getPreloadedState('key', templatingState));
  46. const store: any = { getState, dispatch, subscribe };
  47. const { rerender } = render(
  48. <Provider store={store}>
  49. <Picker {...props} />
  50. </Provider>
  51. );
  52. return { onVariableChange, variable, rerender, dispatch };
  53. }
  54. function getSubMenu(text: string) {
  55. return screen.getByTestId(selectors.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts(text));
  56. }
  57. function getOption(text: string) {
  58. return screen.getByTestId(selectors.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A'));
  59. }
  60. describe('OptionPicker', () => {
  61. describe('when mounted and picker id is not set', () => {
  62. it('should render link with correct text', () => {
  63. setupTestContext();
  64. expect(getSubMenu('A + C')).toBeInTheDocument();
  65. });
  66. it('link text should be clickable', async () => {
  67. const { dispatch } = setupTestContext();
  68. dispatch.mockClear();
  69. await userEvent.click(getSubMenu('A + C'));
  70. expect(dispatch).toHaveBeenCalledTimes(1);
  71. });
  72. });
  73. describe('when mounted and picker id differs from variable id', () => {
  74. it('should render link with correct text', () => {
  75. setupTestContext({
  76. variable: defaultVariable,
  77. pickerState: { id: 'Other' },
  78. });
  79. expect(getSubMenu('A + C')).toBeInTheDocument();
  80. });
  81. it('link text should be clickable', async () => {
  82. const { dispatch } = setupTestContext({
  83. variable: defaultVariable,
  84. pickerState: { id: 'Other' },
  85. });
  86. dispatch.mockClear();
  87. await userEvent.click(getSubMenu('A + C'));
  88. expect(dispatch).toHaveBeenCalledTimes(1);
  89. });
  90. });
  91. describe('when mounted and variable is loading', () => {
  92. it('should render link with correct text and loading indicator should be visible', () => {
  93. setupTestContext({
  94. variable: { ...defaultVariable, state: LoadingState.Loading },
  95. });
  96. expect(getSubMenu('A + C')).toBeInTheDocument();
  97. expect(screen.getByLabelText(selectors.components.LoadingIndicator.icon)).toBeInTheDocument();
  98. });
  99. it('link text should not be clickable', async () => {
  100. const { dispatch } = setupTestContext({
  101. variable: { ...defaultVariable, state: LoadingState.Loading },
  102. });
  103. dispatch.mockClear();
  104. await userEvent.click(getSubMenu('A + C'));
  105. expect(dispatch).toHaveBeenCalledTimes(0);
  106. });
  107. });
  108. describe('when mounted and picker id equals the variable id', () => {
  109. it('should render input, drop down list with correct options', () => {
  110. setupTestContext({
  111. variable: defaultVariable,
  112. pickerState: { id: defaultVariable.id, options: defaultVariable.options, multi: defaultVariable.multi },
  113. });
  114. expect(screen.getByRole('textbox')).toBeInTheDocument();
  115. expect(screen.getByRole('textbox')).toHaveValue('');
  116. expect(
  117. screen.getByLabelText(selectors.pages.Dashboard.SubMenu.submenuItemValueDropDownDropDown)
  118. ).toBeInTheDocument();
  119. expect(getOption('A')).toBeInTheDocument();
  120. expect(getOption('B')).toBeInTheDocument();
  121. expect(getOption('C')).toBeInTheDocument();
  122. });
  123. });
  124. });