ruleBuilder.spec.jsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import {mountWithTheme} from 'sentry-test/enzyme';
  2. import {findOption, openMenu, selectByValueAsync} from 'sentry-test/select-new';
  3. import MemberListStore from 'app/stores/memberListStore';
  4. import ProjectsStore from 'app/stores/projectsStore';
  5. import TeamStore from 'app/stores/teamStore';
  6. import RuleBuilder from 'app/views/settings/project/projectOwnership/ruleBuilder';
  7. describe('RuleBuilder', function () {
  8. const organization = TestStubs.Organization();
  9. let project;
  10. let handleAdd;
  11. const USER_1 = TestStubs.User({
  12. id: '1',
  13. name: 'Jane Bloggs',
  14. email: 'janebloggs@example.com',
  15. user: {
  16. id: '1',
  17. name: 'Jane Bloggs',
  18. email: 'janebloggs@example.com',
  19. },
  20. });
  21. const USER_2 = TestStubs.User({
  22. id: '2',
  23. name: 'John Smith',
  24. email: 'johnsmith@example.com',
  25. user: {
  26. id: '2',
  27. name: 'John Smith',
  28. email: 'johnsmith@example.com',
  29. },
  30. });
  31. const TEAM_1 = TestStubs.Team({
  32. id: '3',
  33. name: 'COOL TEAM',
  34. slug: 'cool-team',
  35. });
  36. // This team is in project
  37. const TEAM_2 = TestStubs.Team({
  38. id: '4',
  39. name: 'TEAM NOT IN PROJECT',
  40. slug: 'team-not-in-project',
  41. });
  42. beforeEach(function () {
  43. // User in project
  44. MemberListStore.loadInitialData([USER_1]);
  45. // All teams
  46. jest.spyOn(TeamStore, 'getAll').mockImplementation(() => [TEAM_1, TEAM_2]);
  47. handleAdd = jest.fn();
  48. project = TestStubs.Project({
  49. // Teams in project
  50. teams: [TEAM_1],
  51. });
  52. ProjectsStore.loadInitialData([project]);
  53. jest.spyOn(ProjectsStore, 'getBySlug').mockImplementation(() => project);
  54. MockApiClient.clearMockResponses();
  55. MockApiClient.addMockResponse({
  56. url: '/organizations/org-slug/members/',
  57. body: [USER_1, USER_2],
  58. });
  59. });
  60. afterEach(function () {});
  61. it('renders', async function () {
  62. const wrapper = mountWithTheme(
  63. <RuleBuilder project={project} organization={organization} onAddRule={handleAdd} />,
  64. TestStubs.routerContext()
  65. );
  66. await tick();
  67. wrapper.update();
  68. const add = wrapper.find('Button');
  69. add.simulate('click');
  70. expect(handleAdd).not.toHaveBeenCalled();
  71. const text = wrapper.find('BuilderInput');
  72. text.simulate('change', {target: {value: 'some/path/*'}});
  73. expect(wrapper.find('Button').prop('disabled')).toBe(true);
  74. add.simulate('click');
  75. expect(handleAdd).not.toHaveBeenCalled();
  76. // Select the first item in the list.
  77. await selectByValueAsync(wrapper, 'user:1', {name: 'owners', control: true});
  78. await wrapper.update();
  79. expect(wrapper.find('Button').prop('disabled')).toBe(false);
  80. add.simulate('click');
  81. expect(handleAdd).toHaveBeenCalled();
  82. // This is because after selecting, react-select (async) reloads
  83. await tick();
  84. wrapper.update();
  85. expect(wrapper.find(RuleBuilder)).toSnapshot();
  86. });
  87. it('renders with suggestions', async function () {
  88. const wrapper = mountWithTheme(
  89. <RuleBuilder
  90. project={project}
  91. organization={organization}
  92. onAddRule={handleAdd}
  93. urls={['example.com/a', 'example.com/a/foo']}
  94. paths={['a/bar', 'a/foo']}
  95. />,
  96. TestStubs.routerContext()
  97. );
  98. // Open the menu so we can do some assertions.
  99. openMenu(wrapper, {name: 'owners', control: true});
  100. await tick();
  101. wrapper.update();
  102. // Should have all 4 users/teams listed
  103. expect(wrapper.find('IdBadge')).toHaveLength(4);
  104. // Should have 1 user not in project and 1 team not in project
  105. expect(wrapper.find('DisabledLabel IdBadge')).toHaveLength(2);
  106. // Team not in project should not be selectable
  107. expect(wrapper.find('DisabledLabel IdBadge').at(0).prop('team').id).toBe('4');
  108. // John Smith should not be selectable
  109. expect(wrapper.find('DisabledLabel IdBadge').at(1).prop('user').id).toBe('2');
  110. // Enter to select Jane Bloggs
  111. findOption(wrapper, {value: 'user:1'}, {name: 'owners', control: true})
  112. .at(0)
  113. .simulate('click');
  114. const ruleCandidate = wrapper.find('RuleCandidate').first();
  115. ruleCandidate.simulate('click');
  116. // This is because after selecting, react-select (async) reloads
  117. await tick();
  118. wrapper.update();
  119. expect(wrapper.find(RuleBuilder)).toSnapshot();
  120. wrapper.find('Button').simulate('click');
  121. expect(handleAdd).toHaveBeenCalled();
  122. });
  123. });