projectsStore.spec.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import {ProjectFixture} from 'sentry-fixture/project';
  2. import {TeamFixture} from 'sentry-fixture/team';
  3. import ProjectsStore from 'sentry/stores/projectsStore';
  4. import TeamStore from 'sentry/stores/teamStore';
  5. describe('ProjectsStore', function () {
  6. const teamFoo = TeamFixture({
  7. slug: 'team-foo',
  8. });
  9. const teamBar = TeamFixture({
  10. slug: 'team-bar',
  11. });
  12. const projectFoo = ProjectFixture({
  13. id: '2',
  14. slug: 'foo',
  15. name: 'Foo',
  16. teams: [teamFoo],
  17. });
  18. const projectBar = ProjectFixture({
  19. id: '10',
  20. slug: 'bar',
  21. name: 'Bar',
  22. teams: [teamFoo, teamBar],
  23. });
  24. describe('setting data', function () {
  25. beforeEach(function () {
  26. ProjectsStore.reset();
  27. });
  28. it('correctly manages loading state', function () {
  29. expect(ProjectsStore.getState()).toMatchObject({
  30. projects: [],
  31. loading: true,
  32. });
  33. ProjectsStore.loadInitialData([projectFoo, projectBar]);
  34. expect(ProjectsStore.getState()).toMatchObject({
  35. projects: [projectBar, projectFoo], // projects are returned sorted
  36. loading: false,
  37. });
  38. });
  39. });
  40. describe('updating data', function () {
  41. beforeEach(function () {
  42. ProjectsStore.reset();
  43. ProjectsStore.loadInitialData([projectFoo, projectBar]);
  44. });
  45. it('updates when slug changes', async function () {
  46. ProjectsStore.onChangeSlug('foo', 'new-project');
  47. await tick();
  48. expect(ProjectsStore.getById(projectFoo.id)).toMatchObject({
  49. slug: 'new-project',
  50. });
  51. expect(ProjectsStore.getById(projectBar.id)).toBeDefined();
  52. });
  53. it('adds project to store on "create success"', function () {
  54. const project = ProjectFixture({id: '11', slug: 'created-project'});
  55. const reloadOrgRequest = MockApiClient.addMockResponse({
  56. url: '/organizations/my-org/',
  57. body: {},
  58. });
  59. MockApiClient.addMockResponse({
  60. url: '/organizations/my-org/projects/',
  61. body: [project, projectBar, projectFoo],
  62. });
  63. MockApiClient.addMockResponse({
  64. url: '/organizations/my-org/teams/',
  65. body: [],
  66. });
  67. ProjectsStore.onCreateSuccess(project, 'my-org');
  68. expect(ProjectsStore.getById(project.id)).toMatchObject({
  69. id: '11',
  70. slug: 'created-project',
  71. });
  72. expect(ProjectsStore.getById(projectFoo.id)).toMatchObject({
  73. id: '2',
  74. slug: 'foo',
  75. name: 'Foo',
  76. });
  77. expect(ProjectsStore.getById(projectBar.id)).toMatchObject({
  78. id: '10',
  79. slug: 'bar',
  80. });
  81. expect(reloadOrgRequest).toHaveBeenCalled();
  82. });
  83. it('updates a project in store', function () {
  84. // Create a new project, but should have same id as `projectBar`
  85. const project = ProjectFixture({id: '10', slug: 'bar', name: 'New Name'});
  86. ProjectsStore.onUpdateSuccess(project);
  87. expect(ProjectsStore.getById(projectBar.id)).toMatchObject({
  88. id: '10',
  89. slug: 'bar',
  90. name: 'New Name',
  91. });
  92. expect(ProjectsStore.getById(projectFoo.id)).toMatchObject({
  93. id: '2',
  94. slug: 'foo',
  95. name: 'Foo',
  96. });
  97. });
  98. it('can remove a team from a single project', function () {
  99. expect(ProjectsStore.getById(projectBar.id)).toMatchObject({
  100. teams: [
  101. expect.objectContaining({slug: 'team-foo'}),
  102. expect.objectContaining({slug: 'team-bar'}),
  103. ],
  104. });
  105. ProjectsStore.onRemoveTeam('team-foo', 'bar');
  106. expect(ProjectsStore.getById(projectBar.id)).toMatchObject({
  107. teams: [expect.objectContaining({slug: 'team-bar'})],
  108. });
  109. expect(ProjectsStore.getById(projectFoo.id)).toMatchObject({
  110. teams: [expect.objectContaining({slug: 'team-foo'})],
  111. });
  112. });
  113. it('removes a team from all projects when team is deleted', function () {
  114. expect(ProjectsStore.getById(projectBar.id)).toMatchObject({
  115. teams: [
  116. expect.objectContaining({slug: 'team-foo'}),
  117. expect.objectContaining({slug: 'team-bar'}),
  118. ],
  119. });
  120. expect(ProjectsStore.getById(projectFoo.id)).toMatchObject({
  121. teams: [expect.objectContaining({slug: 'team-foo'})],
  122. });
  123. TeamStore.onRemoveSuccess('team-foo');
  124. expect(ProjectsStore.getById(projectBar.id)).toMatchObject({
  125. teams: [expect.objectContaining({slug: 'team-bar'})],
  126. });
  127. expect(ProjectsStore.getById(projectFoo.id)).toMatchObject({
  128. teams: [],
  129. });
  130. });
  131. it('can add a team to a project', function () {
  132. const team = TeamFixture({
  133. slug: 'new-team',
  134. });
  135. ProjectsStore.onAddTeam(team, 'foo');
  136. expect(ProjectsStore.getById(projectBar.id)).toMatchObject({
  137. teams: [
  138. expect.objectContaining({slug: 'team-foo'}),
  139. expect.objectContaining({slug: 'team-bar'}),
  140. ],
  141. });
  142. expect(ProjectsStore.getById(projectFoo.id)).toMatchObject({
  143. teams: [
  144. expect.objectContaining({slug: 'team-foo'}),
  145. expect.objectContaining({slug: 'new-team'}),
  146. ],
  147. });
  148. });
  149. });
  150. it('should return a stable reference from getState', function () {
  151. ProjectsStore.loadInitialData([projectFoo, projectBar]);
  152. const state = ProjectsStore.getState();
  153. expect(Object.is(state, ProjectsStore.getState())).toBe(true);
  154. });
  155. });