teamKeyTransactionField.spec.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. import {act, render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  2. import * as TeamKeyTransactionManager from 'sentry/components/performance/teamKeyTransactionsManager';
  3. import ProjectsStore from 'sentry/stores/projectsStore';
  4. import TeamStore from 'sentry/stores/teamStore';
  5. import TeamKeyTransactionField from 'sentry/utils/discover/teamKeyTransactionField';
  6. describe('TeamKeyTransactionField', function () {
  7. const organization = TestStubs.Organization();
  8. const teams = [
  9. TestStubs.Team({id: '1', slug: 'team1', name: 'Team 1'}),
  10. TestStubs.Team({id: '2', slug: 'team2', name: 'Team 2'}),
  11. ];
  12. const project = TestStubs.Project({teams});
  13. beforeEach(function () {
  14. MockApiClient.clearMockResponses();
  15. act(() => ProjectsStore.loadInitialData([project]));
  16. act(() => TeamStore.loadInitialData(teams));
  17. });
  18. it('renders with all teams checked', async function () {
  19. const getTeamKeyTransactionsMock = MockApiClient.addMockResponse({
  20. method: 'GET',
  21. url: `/organizations/${organization.slug}/key-transactions-list/`,
  22. body: teams.map(({id}) => ({
  23. team: id,
  24. count: 1,
  25. keyed: [{project_id: String(project.id), transaction: 'transaction'}],
  26. })),
  27. });
  28. render(
  29. <TeamKeyTransactionManager.Provider
  30. organization={organization}
  31. teams={teams}
  32. selectedTeams={['myteams']}
  33. >
  34. <TeamKeyTransactionField
  35. isKeyTransaction
  36. organization={organization}
  37. projectSlug={project.slug}
  38. transactionName="transaction"
  39. />
  40. </TeamKeyTransactionManager.Provider>
  41. );
  42. await waitFor(() => {
  43. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  44. });
  45. expect(getTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
  46. userEvent.click(screen.getByRole('button', {name: 'Toggle star for team'}));
  47. const [allTeamsCheckbox, teamOneCheckbox, teamTwoCheckbox] =
  48. screen.getAllByRole('checkbox');
  49. expect(allTeamsCheckbox).toBeChecked();
  50. expect(teamOneCheckbox).toBeChecked();
  51. expect(teamTwoCheckbox).toBeChecked();
  52. });
  53. it('renders with some teams checked', async function () {
  54. const getTeamKeyTransactionsMock = MockApiClient.addMockResponse({
  55. method: 'GET',
  56. url: `/organizations/${organization.slug}/key-transactions-list/`,
  57. body: teams.map(({id}) => ({
  58. team: id,
  59. count: id === teams[0].id ? 1 : 0,
  60. keyed:
  61. id === teams[0].id
  62. ? [{project_id: String(project.id), transaction: 'transaction'}]
  63. : [],
  64. })),
  65. });
  66. render(
  67. <TeamKeyTransactionManager.Provider
  68. organization={organization}
  69. teams={teams}
  70. selectedTeams={['myteams']}
  71. >
  72. <TeamKeyTransactionField
  73. isKeyTransaction
  74. organization={organization}
  75. projectSlug={project.slug}
  76. transactionName="transaction"
  77. />
  78. </TeamKeyTransactionManager.Provider>
  79. );
  80. await waitFor(() => {
  81. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  82. });
  83. expect(getTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
  84. userEvent.click(screen.getByRole('button', {name: 'Toggle star for team'}));
  85. const [allTeamsCheckbox, teamOneCheckbox, teamTwoCheckbox] =
  86. screen.getAllByRole('checkbox');
  87. expect(allTeamsCheckbox).not.toBeChecked();
  88. expect(teamOneCheckbox).toBeChecked();
  89. expect(teamTwoCheckbox).not.toBeChecked();
  90. });
  91. it('renders with no teams checked', async function () {
  92. const getTeamKeyTransactionsMock = MockApiClient.addMockResponse({
  93. method: 'GET',
  94. url: `/organizations/${organization.slug}/key-transactions-list/`,
  95. body: teams.map(({id}) => ({
  96. team: id,
  97. count: 0,
  98. keyed: [],
  99. })),
  100. });
  101. render(
  102. <TeamKeyTransactionManager.Provider
  103. organization={organization}
  104. teams={teams}
  105. selectedTeams={['myteams']}
  106. >
  107. <TeamKeyTransactionField
  108. isKeyTransaction
  109. organization={organization}
  110. projectSlug={project.slug}
  111. transactionName="transaction"
  112. />
  113. </TeamKeyTransactionManager.Provider>
  114. );
  115. await waitFor(() => {
  116. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  117. });
  118. expect(getTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
  119. userEvent.click(screen.getByRole('button', {name: 'Toggle star for team'}));
  120. const [allTeamsCheckbox, teamOneCheckbox, teamTwoCheckbox] =
  121. screen.getAllByRole('checkbox');
  122. expect(allTeamsCheckbox).not.toBeChecked();
  123. expect(teamOneCheckbox).not.toBeChecked();
  124. expect(teamTwoCheckbox).not.toBeChecked();
  125. });
  126. it('should be able to check one team', async function () {
  127. MockApiClient.addMockResponse({
  128. method: 'GET',
  129. url: `/organizations/${organization.slug}/key-transactions-list/`,
  130. body: teams.map(({id}) => ({
  131. team: id,
  132. count: 0,
  133. keyed: [],
  134. })),
  135. });
  136. const postTeamKeyTransactionsMock = MockApiClient.addMockResponse({
  137. method: 'POST',
  138. url: '/organizations/org-slug/key-transactions/',
  139. body: [],
  140. match: [
  141. MockApiClient.matchQuery({project: [project.id]}),
  142. MockApiClient.matchData({team: [teams[0].id], transaction: 'transaction'}),
  143. ],
  144. });
  145. render(
  146. <TeamKeyTransactionManager.Provider
  147. organization={organization}
  148. teams={teams}
  149. selectedTeams={['myteams']}
  150. >
  151. <TeamKeyTransactionField
  152. isKeyTransaction
  153. organization={organization}
  154. projectSlug={project.slug}
  155. transactionName="transaction"
  156. />
  157. </TeamKeyTransactionManager.Provider>
  158. );
  159. await waitFor(() => {
  160. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  161. });
  162. userEvent.click(screen.getByRole('button', {name: 'Toggle star for team'}));
  163. const [_allTeamsCheckbox, teamOneCheckbox, _teamTwoCheckbox] =
  164. screen.getAllByRole('checkbox');
  165. expect(teamOneCheckbox).not.toBeChecked();
  166. userEvent.click(teamOneCheckbox);
  167. expect(postTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
  168. await waitFor(() => {
  169. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  170. });
  171. expect(teamOneCheckbox).toBeChecked();
  172. });
  173. it('should be able to uncheck one team', async function () {
  174. MockApiClient.addMockResponse({
  175. method: 'GET',
  176. url: `/organizations/${organization.slug}/key-transactions-list/`,
  177. body: teams.map(({id}) => ({
  178. team: id,
  179. count: 1,
  180. keyed: [{project_id: String(project.id), transaction: 'transaction'}],
  181. })),
  182. });
  183. const deleteTeamKeyTransactionsMock = MockApiClient.addMockResponse({
  184. method: 'DELETE',
  185. url: '/organizations/org-slug/key-transactions/',
  186. body: [],
  187. match: [
  188. MockApiClient.matchQuery({project: [project.id]}),
  189. MockApiClient.matchData({team: [teams[0].id], transaction: 'transaction'}),
  190. ],
  191. });
  192. render(
  193. <TeamKeyTransactionManager.Provider
  194. organization={organization}
  195. teams={teams}
  196. selectedTeams={['myteams']}
  197. >
  198. <TeamKeyTransactionField
  199. isKeyTransaction
  200. organization={organization}
  201. projectSlug={project.slug}
  202. transactionName="transaction"
  203. />
  204. </TeamKeyTransactionManager.Provider>
  205. );
  206. await waitFor(() => {
  207. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  208. });
  209. userEvent.click(screen.getByRole('button', {name: 'Toggle star for team'}));
  210. const [_allTeamsCheckbox, teamOneCheckbox, _teamTwoCheckbox] =
  211. screen.getAllByRole('checkbox');
  212. expect(teamOneCheckbox).toBeChecked();
  213. userEvent.click(teamOneCheckbox);
  214. expect(deleteTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
  215. await waitFor(() => {
  216. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  217. });
  218. expect(teamOneCheckbox).not.toBeChecked();
  219. });
  220. it('should be able to check all with my teams', async function () {
  221. MockApiClient.addMockResponse({
  222. method: 'GET',
  223. url: `/organizations/${organization.slug}/key-transactions-list/`,
  224. body: teams.map(({id}) => ({
  225. team: id,
  226. count: 0,
  227. keyed: [],
  228. })),
  229. });
  230. const postTeamKeyTransactionsMock = MockApiClient.addMockResponse({
  231. method: 'POST',
  232. url: '/organizations/org-slug/key-transactions/',
  233. body: [],
  234. match: [
  235. MockApiClient.matchQuery({project: [project.id]}),
  236. MockApiClient.matchData({
  237. team: [teams[0].id, teams[1].id],
  238. transaction: 'transaction',
  239. }),
  240. ],
  241. });
  242. render(
  243. <TeamKeyTransactionManager.Provider
  244. organization={organization}
  245. teams={teams}
  246. selectedTeams={['myteams']}
  247. >
  248. <TeamKeyTransactionField
  249. isKeyTransaction
  250. organization={organization}
  251. projectSlug={project.slug}
  252. transactionName="transaction"
  253. />
  254. </TeamKeyTransactionManager.Provider>
  255. );
  256. await waitFor(() => {
  257. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  258. });
  259. userEvent.click(screen.getByRole('button', {name: 'Toggle star for team'}));
  260. const [allTeamsCheckbox, teamOneCheckbox, teamTwoCheckbox] =
  261. screen.getAllByRole('checkbox');
  262. expect(allTeamsCheckbox).not.toBeChecked();
  263. userEvent.click(allTeamsCheckbox);
  264. expect(postTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
  265. await waitFor(() => {
  266. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  267. });
  268. expect(allTeamsCheckbox).toBeChecked();
  269. expect(teamOneCheckbox).toBeChecked();
  270. expect(teamTwoCheckbox).toBeChecked();
  271. });
  272. it('should be able to uncheck all with my teams', async function () {
  273. MockApiClient.addMockResponse({
  274. method: 'GET',
  275. url: `/organizations/${organization.slug}/key-transactions-list/`,
  276. body: teams.map(({id}) => ({
  277. team: id,
  278. count: 1,
  279. keyed: [{project_id: String(project.id), transaction: 'transaction'}],
  280. })),
  281. });
  282. const deleteTeamKeyTransactionsMock = MockApiClient.addMockResponse({
  283. method: 'DELETE',
  284. url: '/organizations/org-slug/key-transactions/',
  285. body: [],
  286. match: [
  287. MockApiClient.matchQuery({project: [project.id]}),
  288. MockApiClient.matchData({
  289. team: [teams[0].id, teams[1].id],
  290. transaction: 'transaction',
  291. }),
  292. ],
  293. });
  294. render(
  295. <TeamKeyTransactionManager.Provider
  296. organization={organization}
  297. teams={teams}
  298. selectedTeams={['myteams']}
  299. >
  300. <TeamKeyTransactionField
  301. isKeyTransaction
  302. organization={organization}
  303. projectSlug={project.slug}
  304. transactionName="transaction"
  305. />
  306. </TeamKeyTransactionManager.Provider>
  307. );
  308. await waitFor(() => {
  309. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  310. });
  311. userEvent.click(screen.getByRole('button', {name: 'Toggle star for team'}));
  312. const [allTeamsCheckbox, teamOneCheckbox, teamTwoCheckbox] =
  313. screen.getAllByRole('checkbox');
  314. expect(allTeamsCheckbox).toBeChecked();
  315. userEvent.click(allTeamsCheckbox);
  316. expect(deleteTeamKeyTransactionsMock).toHaveBeenCalledTimes(1);
  317. await waitFor(() => {
  318. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  319. });
  320. expect(allTeamsCheckbox).not.toBeChecked();
  321. expect(teamOneCheckbox).not.toBeChecked();
  322. expect(teamTwoCheckbox).not.toBeChecked();
  323. });
  324. it('should render teams without access separately', async function () {
  325. const myTeams = [...teams, TestStubs.Team({id: '3', slug: 'team3', name: 'Team 3'})];
  326. act(() => {
  327. TeamStore.loadInitialData(myTeams);
  328. });
  329. MockApiClient.addMockResponse({
  330. method: 'GET',
  331. url: `/organizations/${organization.slug}/key-transactions-list/`,
  332. body: myTeams.map(({id}) => ({
  333. team: id,
  334. count: 0,
  335. keyed: [],
  336. })),
  337. });
  338. render(
  339. <TeamKeyTransactionManager.Provider
  340. organization={organization}
  341. teams={myTeams}
  342. selectedTeams={['myteams']}
  343. >
  344. <TeamKeyTransactionField
  345. isKeyTransaction
  346. organization={organization}
  347. projectSlug={project.slug}
  348. transactionName="transaction"
  349. />
  350. </TeamKeyTransactionManager.Provider>
  351. );
  352. await waitFor(() => {
  353. expect(screen.getByRole('button', {name: 'Toggle star for team'})).toBeEnabled();
  354. });
  355. userEvent.click(screen.getByRole('button', {name: 'Toggle star for team'}));
  356. expect(screen.getByText('My Teams with Access')).toBeInTheDocument();
  357. expect(screen.getByText('My Teams without Access')).toBeInTheDocument();
  358. // Only renders checkboxes for teams with access
  359. expect(screen.getAllByRole('checkbox')).toHaveLength(3);
  360. expect(screen.getByText('team3')).toBeInTheDocument();
  361. });
  362. });