github.com/freiheit-com/kuberpult@v1.24.2-0.20240328135542-315d5630abe6/services/frontend-service/src/ui/components/ServiceLane/EnvSelectionDialog.test.tsx (about) 1 /*This file is part of kuberpult. 2 3 Kuberpult is free software: you can redistribute it and/or modify 4 it under the terms of the Expat(MIT) License as published by 5 the Free Software Foundation. 6 7 Kuberpult is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 MIT License for more details. 11 12 You should have received a copy of the MIT License 13 along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>. 14 15 Copyright 2023 freiheit.com*/ 16 import { act, render, getByTestId } from '@testing-library/react'; 17 import { documentQuerySelectorSafe } from '../../../setupTests'; 18 import { EnvSelectionDialog, EnvSelectionDialogProps } from './EnvSelectionDialog'; 19 20 type TestDataSelection = { 21 name: string; 22 input: EnvSelectionDialogProps; 23 expectedNumItems: number; 24 clickOnButton: string; 25 secondClick: string; 26 expectedNumSelectedAfterClick: number; 27 expectedNumDeselectedAfterClick: number; 28 expectedNumSelectedAfterSecondClick: number; 29 }; 30 31 const mySubmitSpy = jest.fn(); 32 const myCancelSpy = jest.fn(); 33 34 const confirmButtonTestId = 'test-confirm-button-confirm'; 35 const cancelButtonTestId = 'test-confirm-button-cancel'; 36 37 const dataSelection: TestDataSelection[] = [ 38 { 39 name: 'renders 2 item list', 40 input: { 41 environments: ['dev', 'staging'], 42 open: true, 43 onSubmit: mySubmitSpy, 44 onCancel: myCancelSpy, 45 envSelectionDialog: true, 46 }, 47 expectedNumItems: 2, 48 clickOnButton: 'dev', 49 expectedNumSelectedAfterClick: 1, 50 expectedNumDeselectedAfterClick: 1, 51 secondClick: 'staging', 52 expectedNumSelectedAfterSecondClick: 2, 53 }, 54 { 55 name: 'renders 3 item list', 56 input: { 57 environments: ['dev', 'staging', 'prod'], 58 open: true, 59 onSubmit: mySubmitSpy, 60 onCancel: myCancelSpy, 61 envSelectionDialog: true, 62 }, 63 expectedNumItems: 3, 64 clickOnButton: 'staging', 65 expectedNumSelectedAfterClick: 1, 66 expectedNumDeselectedAfterClick: 2, 67 secondClick: 'prod', 68 expectedNumSelectedAfterSecondClick: 2, 69 }, 70 { 71 name: 'only one item allowed for release trains', 72 input: { 73 environments: ['dev', 'staging', 'prod'], 74 open: true, 75 onSubmit: mySubmitSpy, 76 onCancel: myCancelSpy, 77 envSelectionDialog: false, 78 }, 79 expectedNumItems: 3, 80 clickOnButton: 'staging', 81 expectedNumSelectedAfterClick: 1, 82 expectedNumDeselectedAfterClick: 2, 83 secondClick: 'prod', 84 expectedNumSelectedAfterSecondClick: 1, 85 }, 86 { 87 name: 'renders empty item list', 88 input: { 89 environments: [], 90 open: true, 91 onSubmit: mySubmitSpy, 92 onCancel: myCancelSpy, 93 envSelectionDialog: true, 94 }, 95 expectedNumItems: 0, 96 clickOnButton: '', 97 expectedNumSelectedAfterClick: 0, 98 expectedNumDeselectedAfterClick: 0, 99 secondClick: '', 100 expectedNumSelectedAfterSecondClick: 0, 101 }, 102 ]; 103 104 type TestDataOpenClose = { 105 name: string; 106 input: EnvSelectionDialogProps; 107 expectedNumElements: number; 108 }; 109 const dataOpenClose: TestDataOpenClose[] = [ 110 { 111 name: 'renders open dialog', 112 input: { 113 environments: ['dev', 'staging', 'prod'], 114 open: true, 115 onSubmit: mySubmitSpy, 116 onCancel: myCancelSpy, 117 envSelectionDialog: true, 118 }, 119 expectedNumElements: 1, 120 }, 121 { 122 name: 'renders closed dialog', 123 input: { 124 environments: ['dev', 'staging', 'prod'], 125 open: false, 126 onSubmit: mySubmitSpy, 127 onCancel: myCancelSpy, 128 envSelectionDialog: true, 129 }, 130 expectedNumElements: 0, 131 }, 132 ]; 133 134 type TestDataCallbacks = { 135 name: string; 136 input: EnvSelectionDialogProps; 137 clickThis: string; 138 expectedCancelCallCount: number; 139 expectedSubmitCallCount: number; 140 }; 141 const dataCallbacks: TestDataCallbacks[] = [ 142 { 143 name: 'renders open dialog', 144 input: { 145 environments: ['dev', 'staging', 'prod'], 146 open: true, 147 onSubmit: mySubmitSpy, 148 onCancel: myCancelSpy, 149 envSelectionDialog: true, 150 }, 151 clickThis: cancelButtonTestId, 152 expectedCancelCallCount: 1, 153 expectedSubmitCallCount: 0, 154 }, 155 { 156 name: 'renders closed dialog', 157 input: { 158 environments: ['dev', 'staging', 'prod'], 159 open: true, 160 onSubmit: mySubmitSpy, 161 onCancel: myCancelSpy, 162 envSelectionDialog: true, 163 }, 164 clickThis: confirmButtonTestId, 165 expectedCancelCallCount: 0, 166 expectedSubmitCallCount: 0, 167 }, 168 ]; 169 170 const getNode = (overrides: EnvSelectionDialogProps) => <EnvSelectionDialog {...overrides} />; 171 const getWrapper = (overrides: EnvSelectionDialogProps) => render(getNode(overrides)); 172 173 describe('EnvSelectionDialog', () => { 174 describe.each(dataSelection)('Test checkbox enabled', (testcase) => { 175 it(testcase.name, () => { 176 mySubmitSpy.mockReset(); 177 myCancelSpy.mockReset(); 178 expect(mySubmitSpy).toHaveBeenCalledTimes(0); 179 expect(myCancelSpy).toHaveBeenCalledTimes(0); 180 181 getWrapper(testcase.input); 182 183 expect(document.querySelectorAll('.envs-dropdown-select .test-button-checkbox').length).toEqual( 184 testcase.expectedNumItems 185 ); 186 if (testcase.clickOnButton !== '') { 187 const result = documentQuerySelectorSafe('.id-' + testcase.clickOnButton); 188 act(() => { 189 result.click(); 190 }); 191 } else { 192 expect(document.querySelector('.env-selection-dialog')?.textContent).toContain( 193 'There are no environments' 194 ); 195 } 196 expect(document.querySelectorAll('.test-button-checkbox.enabled').length).toEqual( 197 testcase.expectedNumSelectedAfterClick 198 ); 199 expect(document.querySelectorAll('.test-button-checkbox.disabled').length).toEqual( 200 testcase.expectedNumDeselectedAfterClick 201 ); 202 if (testcase.secondClick !== '') { 203 const result = documentQuerySelectorSafe('.id-' + testcase.secondClick); 204 act(() => { 205 result.click(); 206 }); 207 } 208 expect(document.querySelectorAll('.test-button-checkbox.enabled').length).toEqual( 209 testcase.expectedNumSelectedAfterSecondClick 210 ); 211 }); 212 }); 213 describe.each(dataOpenClose)('open/close', (testcase) => { 214 it(testcase.name, () => { 215 getWrapper(testcase.input); 216 expect(document.querySelectorAll('.envs-dropdown-select').length).toEqual(testcase.expectedNumElements); 217 }); 218 }); 219 describe.each(dataCallbacks)('submit/cancel callbacks', (testcase) => { 220 it(testcase.name, () => { 221 mySubmitSpy.mockReset(); 222 myCancelSpy.mockReset(); 223 expect(mySubmitSpy).toHaveBeenCalledTimes(0); 224 expect(myCancelSpy).toHaveBeenCalledTimes(0); 225 226 const { container } = getWrapper(testcase.input); 227 228 const theButton = getByTestId(container, testcase.clickThis); 229 act(() => { 230 theButton.click(); 231 }); 232 getByTestId(container, testcase.clickThis); // should not crash 233 234 expect(myCancelSpy).toHaveBeenCalledTimes(testcase.expectedCancelCallCount); 235 expect(mySubmitSpy).toHaveBeenCalledTimes(testcase.expectedSubmitCallCount); 236 }); 237 }); 238 239 type TestDataAddTeam = { 240 name: string; 241 input: EnvSelectionDialogProps; 242 clickTheseTeams: string[]; 243 expectedCancelCallCount: number; 244 expectedSubmitCallCount: number; 245 expectedSubmitCalledWith: string[]; 246 }; 247 const addTeamArray: TestDataAddTeam[] = [ 248 { 249 name: '1 env', 250 input: { 251 environments: ['dev', 'staging', 'prod'], 252 open: true, 253 onSubmit: mySubmitSpy, 254 onCancel: myCancelSpy, 255 envSelectionDialog: true, 256 }, 257 clickTheseTeams: ['dev'], 258 expectedCancelCallCount: 0, 259 expectedSubmitCallCount: 1, 260 expectedSubmitCalledWith: ['dev'], 261 }, 262 { 263 name: '2 envs', 264 input: { 265 environments: ['dev', 'staging', 'prod'], 266 open: true, 267 onSubmit: mySubmitSpy, 268 onCancel: myCancelSpy, 269 envSelectionDialog: true, 270 }, 271 clickTheseTeams: ['staging', 'prod'], 272 expectedCancelCallCount: 0, 273 expectedSubmitCallCount: 1, 274 expectedSubmitCalledWith: ['staging', 'prod'], 275 }, 276 { 277 name: '1 env clicked twice', 278 input: { 279 environments: ['dev', 'staging', 'prod'], 280 open: true, 281 onSubmit: mySubmitSpy, 282 onCancel: myCancelSpy, 283 envSelectionDialog: true, 284 }, 285 clickTheseTeams: ['dev', 'staging', 'staging'], 286 expectedCancelCallCount: 0, 287 expectedSubmitCallCount: 1, 288 expectedSubmitCalledWith: ['dev'], 289 }, 290 ]; 291 describe.each(addTeamArray)('adding 2 teams works', (testcase) => { 292 it(testcase.name, () => { 293 mySubmitSpy.mockReset(); 294 myCancelSpy.mockReset(); 295 expect(mySubmitSpy).toHaveBeenCalledTimes(0); 296 expect(myCancelSpy).toHaveBeenCalledTimes(0); 297 298 const { container } = getWrapper(testcase.input); 299 300 testcase.clickTheseTeams.forEach((value, index) => { 301 const teamButton = documentQuerySelectorSafe('.id-' + value); 302 act(() => { 303 teamButton.click(); 304 }); 305 }); 306 const confirmButton = getByTestId(container, confirmButtonTestId); 307 act(() => { 308 confirmButton.click(); 309 }); 310 311 expect(myCancelSpy).toHaveBeenCalledTimes(testcase.expectedCancelCallCount); 312 expect(mySubmitSpy).toHaveBeenCalledTimes(testcase.expectedSubmitCallCount); 313 expect(mySubmitSpy).toHaveBeenCalledWith(testcase.expectedSubmitCalledWith); 314 }); 315 }); 316 });