organizationTeamProjects.spec.jsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import {mountWithTheme} from 'sentry-test/enzyme';
  2. import {initializeOrg} from 'sentry-test/initializeOrg';
  3. import {Client} from 'sentry/api';
  4. import {TeamProjects as OrganizationTeamProjects} from 'sentry/views/settings/organizationTeams/teamProjects';
  5. describe('OrganizationTeamProjects', function () {
  6. let team;
  7. let getMock;
  8. let putMock;
  9. let postMock;
  10. let deleteMock;
  11. const project = TestStubs.Project({teams: [team]});
  12. const project2 = TestStubs.Project({
  13. id: '3',
  14. slug: 'project-slug-2',
  15. name: 'Project Name 2',
  16. });
  17. const {routerContext, organization} = initializeOrg({
  18. organization: TestStubs.Organization({slug: 'org-slug'}),
  19. projects: [project, project2],
  20. });
  21. beforeEach(function () {
  22. team = TestStubs.Team({slug: 'team-slug'});
  23. getMock = Client.addMockResponse({
  24. url: '/organizations/org-slug/projects/',
  25. body: [project, project2],
  26. });
  27. putMock = Client.addMockResponse({
  28. method: 'PUT',
  29. url: '/projects/org-slug/project-slug/',
  30. body: project,
  31. });
  32. postMock = Client.addMockResponse({
  33. method: 'POST',
  34. url: `/projects/org-slug/${project2.slug}/teams/${team.slug}/`,
  35. body: {...project2, teams: [team]},
  36. status: 201,
  37. });
  38. deleteMock = Client.addMockResponse({
  39. method: 'DELETE',
  40. url: `/projects/org-slug/${project2.slug}/teams/${team.slug}/`,
  41. body: {...project2, teams: []},
  42. status: 204,
  43. });
  44. });
  45. afterEach(function () {
  46. Client.clearMockResponses();
  47. });
  48. it('fetches linked and unlinked projects', function () {
  49. mountWithTheme(
  50. <OrganizationTeamProjects
  51. api={new MockApiClient()}
  52. organization={organization}
  53. params={{orgId: 'org-slug', teamId: team.slug}}
  54. location={{query: {}}}
  55. />,
  56. routerContext
  57. );
  58. expect(getMock).toHaveBeenCalledTimes(2);
  59. expect(getMock.mock.calls[0][1].query.query).toBe('team:team-slug');
  60. expect(getMock.mock.calls[1][1].query.query).toBe('!team:team-slug');
  61. });
  62. it('Should render', async function () {
  63. const wrapper = mountWithTheme(
  64. <OrganizationTeamProjects
  65. api={new MockApiClient()}
  66. organization={organization}
  67. params={{orgId: 'org-slug', teamId: team.slug}}
  68. location={{query: {}}}
  69. />,
  70. routerContext
  71. );
  72. await tick();
  73. wrapper.update();
  74. expect(wrapper).toSnapshot();
  75. expect(wrapper.find('ProjectBadge').first().text()).toBe('project-slug');
  76. });
  77. it('Should allow bookmarking', async function () {
  78. const wrapper = mountWithTheme(
  79. <OrganizationTeamProjects
  80. api={new MockApiClient()}
  81. organization={organization}
  82. params={{orgId: 'org-slug', teamId: team.slug}}
  83. location={{query: {}}}
  84. />,
  85. routerContext
  86. );
  87. await tick();
  88. wrapper.update();
  89. const stars = wrapper.find('BookmarkStar');
  90. expect(stars).toHaveLength(2);
  91. stars.first().simulate('click');
  92. expect(wrapper.find('BookmarkStar').first().prop('isBookmarked')).toBeTruthy();
  93. expect(putMock).toHaveBeenCalledTimes(1);
  94. });
  95. it('Should allow adding and removing projects', async function () {
  96. const wrapper = mountWithTheme(
  97. <OrganizationTeamProjects
  98. api={new MockApiClient()}
  99. organization={organization}
  100. params={{orgId: 'org-slug', teamId: team.slug}}
  101. location={{query: {}}}
  102. />,
  103. routerContext
  104. );
  105. await tick();
  106. wrapper.update();
  107. const add = wrapper.find('DropdownButton').first();
  108. add.simulate('click');
  109. const el = wrapper.find('AutoCompleteItem').at(1);
  110. el.simulate('click');
  111. wrapper.update();
  112. expect(postMock).toHaveBeenCalledTimes(1);
  113. await tick();
  114. wrapper.update();
  115. // find second project's remove button
  116. const remove = wrapper.find('PanelBody Button[aria-label="Remove"]').at(1);
  117. remove.simulate('click');
  118. expect(deleteMock).toHaveBeenCalledTimes(1);
  119. });
  120. it('handles filtering unlinked projects', async function () {
  121. const wrapper = mountWithTheme(
  122. <OrganizationTeamProjects
  123. api={new MockApiClient()}
  124. organization={organization}
  125. params={{orgId: 'org-slug', teamId: team.slug}}
  126. location={{query: {}}}
  127. />,
  128. routerContext
  129. );
  130. await tick();
  131. wrapper.update();
  132. expect(getMock).toHaveBeenCalledTimes(2);
  133. const add = wrapper.find('DropdownButton').first();
  134. add.simulate('click');
  135. const input = wrapper.find('StyledInput');
  136. input.simulate('change', {target: {value: 'a'}});
  137. expect(getMock).toHaveBeenCalledTimes(3);
  138. expect(getMock).toHaveBeenCalledWith(
  139. '/organizations/org-slug/projects/',
  140. expect.objectContaining({
  141. query: expect.objectContaining({
  142. query: '!team:team-slug a',
  143. }),
  144. })
  145. );
  146. });
  147. });