ownershipInput.spec.jsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import React from 'react';
  2. import {mountWithTheme} from 'sentry-test/enzyme';
  3. import {findOption, openMenu} from 'sentry-test/select';
  4. import MemberListStore from 'app/stores/memberListStore';
  5. import OwnerInput from 'app/views/settings/project/projectOwnership/ownerInput';
  6. describe('Project Ownership Input', function () {
  7. let org;
  8. let project;
  9. let put;
  10. beforeEach(function () {
  11. org = TestStubs.Organization();
  12. project = TestStubs.Project();
  13. MockApiClient.addMockResponse({
  14. url: '/organizations/org-slug/members/',
  15. method: 'GET',
  16. body: TestStubs.Members(),
  17. });
  18. put = MockApiClient.addMockResponse({
  19. url: `/projects/${org.slug}/${project.slug}/ownership/`,
  20. method: 'PUT',
  21. body: {raw: 'url:src @dummy@example.com'},
  22. });
  23. MemberListStore.loadInitialData([
  24. TestStubs.User({id: '1', email: 'bob@example.com'}),
  25. ]);
  26. });
  27. afterEach(function () {
  28. MemberListStore.init();
  29. });
  30. it('renders', function () {
  31. const wrapper = mountWithTheme(
  32. <OwnerInput
  33. params={{orgId: org.slug, projectId: project.slug}}
  34. organization={org}
  35. initialText="url:src @dummy@example.com"
  36. project={project}
  37. />,
  38. TestStubs.routerContext()
  39. );
  40. const submit = wrapper.find('SaveButton button');
  41. expect(put).not.toHaveBeenCalled();
  42. // if text is unchanged, submit button is disabled
  43. submit.simulate('click');
  44. expect(put).not.toHaveBeenCalled();
  45. wrapper.find('StyledTextArea').simulate('change', {target: {value: 'new'}});
  46. submit.simulate('click');
  47. expect(put).toHaveBeenCalled();
  48. expect(wrapper.find(OwnerInput)).toSnapshot();
  49. });
  50. it('updates on add preserving existing text', async function () {
  51. const wrapper = mountWithTheme(
  52. <OwnerInput
  53. params={{orgId: org.slug, projectId: project.slug}}
  54. organization={org}
  55. initialText="url:src @dummy@example.com"
  56. project={project}
  57. />,
  58. TestStubs.routerContext()
  59. );
  60. // Set a path, as path is selected bu default.
  61. const pathInput = wrapper.find('RuleBuilder BuilderInput');
  62. pathInput.simulate('change', {target: {value: 'file.js'}});
  63. // Select the user.
  64. let userSelect = wrapper.find('RuleBuilder SelectOwners');
  65. openMenu(userSelect, {control: true});
  66. await tick();
  67. await wrapper.update();
  68. // Because this menu is async we can't use selectByValue()
  69. userSelect = wrapper.find('RuleBuilder SelectOwners');
  70. findOption(userSelect, {value: 'user:1'}, {control: true})
  71. .at(0)
  72. .simulate('mouseDown');
  73. await wrapper.update();
  74. // Add the new rule.
  75. const button = wrapper.find('RuleBuilder AddButton button');
  76. button.simulate('click');
  77. expect(put).toHaveBeenCalledWith(
  78. '/projects/org-slug/project-slug/ownership/',
  79. expect.objectContaining({
  80. data: {
  81. raw: 'url:src @dummy@example.com' + '\n' + 'path:file.js bob@example.com',
  82. },
  83. })
  84. );
  85. });
  86. });