multipleEnvironmentSelector.spec.jsx 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. import {mountWithTheme} from 'sentry-test/enzyme';
  2. import MultipleEnvironmentSelector from 'app/components/organizations/multipleEnvironmentSelector';
  3. import {ALL_ACCESS_PROJECTS} from 'app/constants/globalSelectionHeader';
  4. import ConfigStore from 'app/stores/configStore';
  5. describe('MultipleEnvironmentSelector', function () {
  6. let wrapper;
  7. const onChange = jest.fn();
  8. const onUpdate = jest.fn();
  9. const envs = ['production', 'staging', 'dev'];
  10. const projects = [
  11. TestStubs.Project({
  12. id: '1',
  13. slug: 'first',
  14. environments: ['production', 'staging'],
  15. }),
  16. TestStubs.Project({
  17. id: '2',
  18. slug: 'second',
  19. environments: ['dev'],
  20. }),
  21. TestStubs.Project({
  22. id: '3',
  23. slug: 'no member',
  24. environments: ['no-env'],
  25. isMember: false,
  26. }),
  27. ];
  28. const organization = TestStubs.Organization({projects});
  29. const selectedProjects = [1, 2];
  30. const routerContext = TestStubs.routerContext([
  31. {
  32. organization,
  33. },
  34. ]);
  35. beforeEach(function () {
  36. onChange.mockReset();
  37. onUpdate.mockReset();
  38. wrapper = mountWithTheme(
  39. <MultipleEnvironmentSelector
  40. organization={organization}
  41. projects={projects}
  42. loadingProjects={false}
  43. selectedProjects={selectedProjects}
  44. onChange={onChange}
  45. onUpdate={onUpdate}
  46. />,
  47. routerContext
  48. );
  49. });
  50. it('can select and change environments', async function () {
  51. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  52. // Select all envs
  53. envs.forEach((_env, i) => {
  54. wrapper
  55. .find('EnvironmentSelectorItem')
  56. .at(i)
  57. .find('CheckboxHitbox')
  58. .simulate('click', {});
  59. });
  60. expect(onChange).toHaveBeenCalledTimes(3);
  61. expect(onChange).toHaveBeenLastCalledWith(envs);
  62. wrapper
  63. .find('MultipleSelectorSubmitRow button[aria-label="Apply"]')
  64. .simulate('click');
  65. expect(onUpdate).toHaveBeenCalledWith();
  66. });
  67. it('selects multiple environments and uses chevron to update', async function () {
  68. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  69. await wrapper
  70. .find('MultipleEnvironmentSelector AutoCompleteItem CheckboxHitbox')
  71. .at(0)
  72. .simulate('click');
  73. expect(onChange).toHaveBeenLastCalledWith(['production']);
  74. wrapper
  75. .find('MultipleEnvironmentSelector AutoCompleteItem CheckboxHitbox')
  76. .at(1)
  77. .simulate('click');
  78. expect(onChange).toHaveBeenLastCalledWith(['production', 'staging']);
  79. wrapper.find('MultipleEnvironmentSelector StyledChevron').simulate('click');
  80. expect(onUpdate).toHaveBeenCalledWith();
  81. });
  82. it('does not update when there are no changes', async function () {
  83. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  84. wrapper.find('MultipleEnvironmentSelector StyledChevron').simulate('click');
  85. expect(onUpdate).not.toHaveBeenCalled();
  86. });
  87. it('updates environment options when projects selection changes', async function () {
  88. // project 2 only has 1 environment.
  89. wrapper.setProps({selectedProjects: [2]});
  90. wrapper.update();
  91. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  92. const items = wrapper.find('MultipleEnvironmentSelector GlobalSelectionHeaderRow');
  93. expect(items.length).toEqual(1);
  94. expect(items.at(0).text()).toBe('dev');
  95. });
  96. it('shows non-member project environments when selected', async function () {
  97. wrapper.setProps({selectedProjects: [3]});
  98. wrapper.update();
  99. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  100. const items = wrapper.find('MultipleEnvironmentSelector GlobalSelectionHeaderRow');
  101. expect(items.length).toEqual(1);
  102. expect(items.at(0).text()).toBe('no-env');
  103. });
  104. it('shows member project environments when there are no projects selected', async function () {
  105. wrapper.setProps({selectedProjects: []});
  106. wrapper.update();
  107. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  108. const items = wrapper.find('MultipleEnvironmentSelector GlobalSelectionHeaderRow');
  109. expect(items.length).toEqual(3);
  110. expect(items.at(0).text()).toBe('production');
  111. expect(items.at(1).text()).toBe('staging');
  112. expect(items.at(2).text()).toBe('dev');
  113. });
  114. it('shows My Projects/all environments (superuser - no team belonging)', async function () {
  115. ConfigStore.config = {
  116. user: {
  117. isSuperuser: true,
  118. },
  119. };
  120. // "My Projects" view
  121. wrapper.setProps({selectedProjects: []});
  122. // This user is member of no project
  123. wrapper.setProps({
  124. projects: [
  125. TestStubs.Project({
  126. id: '1',
  127. slug: 'first',
  128. environments: ['production', 'staging'],
  129. isMember: false,
  130. }),
  131. TestStubs.Project({
  132. id: '2',
  133. slug: 'second',
  134. environments: ['dev'],
  135. isMember: false,
  136. }),
  137. ],
  138. });
  139. wrapper.update();
  140. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  141. const items = wrapper.find('MultipleEnvironmentSelector GlobalSelectionHeaderRow');
  142. expect(items.length).toEqual(3);
  143. expect(items.at(0).text()).toBe('production');
  144. expect(items.at(1).text()).toBe('staging');
  145. expect(items.at(2).text()).toBe('dev');
  146. });
  147. it('shows My Projects/all environments (superuser - belongs one team)', async function () {
  148. // XXX: Ideally, "My Projects" and "All Projects" should be different if a superuser
  149. // was to belong to at least one project
  150. ConfigStore.config = {
  151. user: {
  152. isSuperuser: true,
  153. },
  154. };
  155. // "My Projects" view
  156. wrapper.setProps({selectedProjects: []});
  157. // This user is member of one project
  158. wrapper.setProps({
  159. projects: [
  160. TestStubs.Project({
  161. id: '1',
  162. slug: 'first',
  163. environments: ['production', 'staging'],
  164. }),
  165. TestStubs.Project({
  166. id: '2',
  167. slug: 'second',
  168. environments: ['dev'],
  169. isMember: false,
  170. }),
  171. ],
  172. });
  173. wrapper.update();
  174. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  175. const items = wrapper.find('MultipleEnvironmentSelector GlobalSelectionHeaderRow');
  176. expect(items.length).toEqual(3);
  177. expect(items.at(0).text()).toBe('production');
  178. expect(items.at(1).text()).toBe('staging');
  179. expect(items.at(2).text()).toBe('dev');
  180. });
  181. it('shows All Projects/all environments (superuser - no team belonging)', async function () {
  182. ConfigStore.config = {
  183. user: {
  184. isSuperuser: true,
  185. },
  186. };
  187. // "All Projects" view
  188. wrapper.setProps({selectedProjects: [-1]});
  189. // This user is member of one project
  190. wrapper.setProps({
  191. projects: [
  192. TestStubs.Project({
  193. id: '1',
  194. slug: 'first',
  195. environments: ['production', 'staging'],
  196. }),
  197. TestStubs.Project({
  198. id: '2',
  199. slug: 'second',
  200. environments: ['dev'],
  201. isMember: false,
  202. }),
  203. ],
  204. });
  205. wrapper.update();
  206. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  207. const items = wrapper.find('MultipleEnvironmentSelector GlobalSelectionHeaderRow');
  208. expect(items.length).toEqual(3);
  209. expect(items.at(0).text()).toBe('production');
  210. expect(items.at(1).text()).toBe('staging');
  211. expect(items.at(2).text()).toBe('dev');
  212. });
  213. it('shows All Projects/all environments (superuser - belongs one team)', async function () {
  214. // XXX: Ideally, "My Projects" and "All Projects" should be different if a superuser
  215. // was to belong to at least one project
  216. ConfigStore.config = {
  217. user: {
  218. isSuperuser: true,
  219. },
  220. };
  221. // "All Projects" view
  222. wrapper.setProps({selectedProjects: [-1]});
  223. // This user is member of one project
  224. wrapper.setProps({
  225. projects: [
  226. TestStubs.Project({
  227. id: '1',
  228. slug: 'first',
  229. environments: ['production', 'staging'],
  230. }),
  231. TestStubs.Project({
  232. id: '2',
  233. slug: 'second',
  234. environments: ['dev'],
  235. isMember: false,
  236. }),
  237. ],
  238. });
  239. wrapper.update();
  240. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  241. const items = wrapper.find('MultipleEnvironmentSelector GlobalSelectionHeaderRow');
  242. expect(items.length).toEqual(3);
  243. expect(items.at(0).text()).toBe('production');
  244. expect(items.at(1).text()).toBe('staging');
  245. expect(items.at(2).text()).toBe('dev');
  246. });
  247. it('shows all project environments when "all projects" is selected', async function () {
  248. wrapper.setProps({selectedProjects: [ALL_ACCESS_PROJECTS]});
  249. wrapper.update();
  250. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  251. const items = wrapper.find('MultipleEnvironmentSelector GlobalSelectionHeaderRow');
  252. expect(items.length).toEqual(4);
  253. expect(items.at(0).text()).toBe('production');
  254. expect(items.at(1).text()).toBe('staging');
  255. expect(items.at(2).text()).toBe('dev');
  256. expect(items.at(3).text()).toBe('no-env');
  257. });
  258. it('shows the distinct union of environments across all projects', async function () {
  259. wrapper.setProps({selectedProjects: [1, 2]});
  260. await wrapper.find('MultipleEnvironmentSelector HeaderItem').simulate('click');
  261. const items = wrapper.find('MultipleEnvironmentSelector GlobalSelectionHeaderRow');
  262. expect(items.length).toEqual(3);
  263. expect(items.at(0).text()).toBe('production');
  264. expect(items.at(1).text()).toBe('staging');
  265. expect(items.at(2).text()).toBe('dev');
  266. });
  267. });