github.com/freiheit-com/kuberpult@v1.24.2-0.20240328135542-315d5630abe6/services/frontend-service/src/ui/Pages/Home/Home.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 { render, renderHook } from '@testing-library/react'; 17 import { Home } from './Home'; 18 import { searchCustomFilter, UpdateOverview, useApplicationsFilteredAndSorted, useTeamNames } from '../../utils/store'; 19 import { Spy } from 'spy4js'; 20 import { MemoryRouter } from 'react-router-dom'; 21 import { Application, UndeploySummary } from '../../../api/api'; 22 import { fakeLoadEverything } from '../../../setupTests'; 23 24 const mock_ServiceLane = Spy.mockReactComponents('../../components/ServiceLane/ServiceLane', 'ServiceLane'); 25 26 describe('App', () => { 27 const getNode = (): JSX.Element | any => ( 28 <MemoryRouter> 29 <Home /> 30 </MemoryRouter> 31 ); 32 const getWrapper = () => render(getNode()); 33 it('Renders full app', () => { 34 const buildTestApp = (suffix: string): Application => ({ 35 name: `test${suffix}`, 36 releases: [], 37 sourceRepoUrl: `http://test${suffix}.com`, 38 team: `team${suffix}`, 39 undeploySummary: UndeploySummary.NORMAL, 40 warnings: [], 41 }); 42 // when 43 const sampleApps = { 44 app1: buildTestApp('1'), 45 app2: buildTestApp('2'), 46 app3: buildTestApp('3'), 47 }; 48 UpdateOverview.set({ 49 applications: sampleApps, 50 }); 51 fakeLoadEverything(true); 52 getWrapper(); 53 54 // then apps are sorted and Service Lane is called 55 expect(mock_ServiceLane.ServiceLane.getCallArgument(0, 0)).toStrictEqual({ application: sampleApps.app1 }); 56 expect(mock_ServiceLane.ServiceLane.getCallArgument(1, 0)).toStrictEqual({ application: sampleApps.app2 }); 57 expect(mock_ServiceLane.ServiceLane.getCallArgument(2, 0)).toStrictEqual({ application: sampleApps.app3 }); 58 }); 59 it('Renders Spinner', () => { 60 // given 61 UpdateOverview.set({ 62 loaded: false, 63 }); 64 // when 65 const { container } = getWrapper(); 66 // then 67 expect(container.getElementsByClassName('spinner')).toHaveLength(1); 68 }); 69 }); 70 71 describe('Get teams from application list (useTeamNames)', () => { 72 interface dataT { 73 name: string; 74 applications: { [key: string]: Application }; 75 expectedTeams: string[]; 76 } 77 78 const data: dataT[] = [ 79 { 80 name: 'right amount of teams - 4 sorted results', 81 applications: { 82 foo: { 83 name: 'foo', 84 releases: [], 85 sourceRepoUrl: 'http://foo.com', 86 team: 'dummy', 87 undeploySummary: UndeploySummary.NORMAL, 88 warnings: [], 89 }, 90 bar: { 91 name: 'bar', 92 releases: [], 93 sourceRepoUrl: 'http://bar.com', 94 team: 'test', 95 undeploySummary: UndeploySummary.NORMAL, 96 warnings: [], 97 }, 98 example: { 99 name: 'example', 100 releases: [], 101 sourceRepoUrl: 'http://example.com', 102 team: 'test2', 103 undeploySummary: UndeploySummary.NORMAL, 104 warnings: [], 105 }, 106 team: { 107 name: 'team', 108 releases: [], 109 sourceRepoUrl: 'http://team.com', 110 team: 'foo', 111 undeploySummary: UndeploySummary.NORMAL, 112 warnings: [], 113 }, 114 }, 115 expectedTeams: ['dummy', 'foo', 'test', 'test2'], 116 }, 117 { 118 name: "doesn't collect duplicate team names - 2 sorted results", 119 applications: { 120 foo: { 121 name: 'foo', 122 releases: [], 123 sourceRepoUrl: 'http://foo.com', 124 team: 'dummy', 125 undeploySummary: UndeploySummary.NORMAL, 126 warnings: [], 127 }, 128 bar: { 129 name: 'bar', 130 releases: [], 131 sourceRepoUrl: 'http://bar.com', 132 team: 'dummy', 133 undeploySummary: UndeploySummary.NORMAL, 134 warnings: [], 135 }, 136 team: { 137 name: 'team', 138 releases: [], 139 sourceRepoUrl: 'http://team.com', 140 team: 'foo', 141 undeploySummary: UndeploySummary.NORMAL, 142 warnings: [], 143 }, 144 }, 145 expectedTeams: ['dummy', 'foo'], 146 }, 147 { 148 name: "doesn't collect empty team names and adds <No Team> option to dropdown - 2 sorted results", 149 applications: { 150 foo: { 151 name: 'foo', 152 releases: [], 153 sourceRepoUrl: 'http://foo.com', 154 team: '', 155 undeploySummary: UndeploySummary.NORMAL, 156 warnings: [], 157 }, 158 bar: { 159 name: 'bar', 160 releases: [], 161 sourceRepoUrl: 'http://bar.com', 162 team: 'test', 163 undeploySummary: UndeploySummary.NORMAL, 164 warnings: [], 165 }, 166 example: { 167 name: 'example', 168 releases: [], 169 sourceRepoUrl: 'http://example.com', 170 team: '', 171 undeploySummary: UndeploySummary.NORMAL, 172 warnings: [], 173 }, 174 team: { 175 name: 'team', 176 releases: [], 177 sourceRepoUrl: 'http://team.com', 178 team: 'foo', 179 undeploySummary: UndeploySummary.NORMAL, 180 warnings: [], 181 }, 182 }, 183 expectedTeams: ['<No Team>', 'foo', 'test'], 184 }, 185 ]; 186 187 describe.each(data)(`Renders an Application Card`, (testcase) => { 188 it(testcase.name, () => { 189 // given 190 UpdateOverview.set({ applications: testcase.applications }); 191 // when 192 const teamNames = renderHook(() => useTeamNames()).result.current; 193 expect(teamNames).toStrictEqual(testcase.expectedTeams); 194 }); 195 }); 196 }); 197 198 describe('Get applications from selected teams (useApplicationsFilteredAndSorted)', () => { 199 interface dataT { 200 name: string; 201 selectedTeams: string[]; 202 applications: { [key: string]: Application }; 203 expectedNumOfTeams: number; 204 } 205 206 const data: dataT[] = [ 207 { 208 name: 'gets filtered apps by team - 2 results', 209 selectedTeams: ['dummy', 'foo'], 210 applications: { 211 foo: { 212 name: 'foo', 213 releases: [], 214 sourceRepoUrl: 'http://foo.com', 215 team: 'dummy', 216 undeploySummary: UndeploySummary.NORMAL, 217 warnings: [], 218 }, 219 bar: { 220 name: 'bar', 221 releases: [], 222 sourceRepoUrl: 'http://bar.com', 223 team: 'test', 224 undeploySummary: UndeploySummary.NORMAL, 225 warnings: [], 226 }, 227 example: { 228 name: 'example', 229 releases: [], 230 sourceRepoUrl: 'http://example.com', 231 team: 'test2', 232 undeploySummary: UndeploySummary.NORMAL, 233 warnings: [], 234 }, 235 team: { 236 name: 'team', 237 releases: [], 238 sourceRepoUrl: 'http://team.com', 239 team: 'foo', 240 undeploySummary: UndeploySummary.NORMAL, 241 warnings: [], 242 }, 243 }, 244 expectedNumOfTeams: 2, 245 }, 246 { 247 name: 'shows both applications of the selected team - 2 results', 248 selectedTeams: ['dummy'], 249 applications: { 250 foo: { 251 name: 'foo', 252 releases: [], 253 sourceRepoUrl: 'http://foo.com', 254 team: 'dummy', 255 undeploySummary: UndeploySummary.NORMAL, 256 warnings: [], 257 }, 258 bar: { 259 name: 'bar', 260 releases: [], 261 sourceRepoUrl: 'http://bar.com', 262 team: 'dummy', 263 undeploySummary: UndeploySummary.NORMAL, 264 warnings: [], 265 }, 266 team: { 267 name: 'team', 268 releases: [], 269 sourceRepoUrl: 'http://team.com', 270 team: 'foo', 271 undeploySummary: UndeploySummary.NORMAL, 272 warnings: [], 273 }, 274 }, 275 expectedNumOfTeams: 2, 276 }, 277 { 278 name: 'no teams selected (shows every application) - 4 results', 279 selectedTeams: [], 280 applications: { 281 foo: { 282 name: 'foo', 283 releases: [], 284 sourceRepoUrl: 'http://foo.com', 285 team: '', 286 undeploySummary: UndeploySummary.NORMAL, 287 warnings: [], 288 }, 289 bar: { 290 name: 'bar', 291 releases: [], 292 sourceRepoUrl: 'http://bar.com', 293 team: 'test', 294 undeploySummary: UndeploySummary.NORMAL, 295 warnings: [], 296 }, 297 example: { 298 name: 'example', 299 releases: [], 300 sourceRepoUrl: 'http://example.com', 301 team: '', 302 undeploySummary: UndeploySummary.NORMAL, 303 warnings: [], 304 }, 305 team: { 306 name: 'team', 307 releases: [], 308 sourceRepoUrl: 'http://team.com', 309 team: 'foo', 310 undeploySummary: UndeploySummary.NORMAL, 311 warnings: [], 312 }, 313 }, 314 expectedNumOfTeams: 4, 315 }, 316 { 317 name: 'selected team has no assigned applications - 0 results', 318 selectedTeams: ['thisTeamDoesntExist'], 319 applications: { 320 foo: { 321 name: 'foo', 322 releases: [], 323 sourceRepoUrl: 'http://foo.com', 324 team: 'dummy', 325 undeploySummary: UndeploySummary.NORMAL, 326 warnings: [], 327 }, 328 bar: { 329 name: 'bar', 330 releases: [], 331 sourceRepoUrl: 'http://bar.com', 332 team: 'test', 333 undeploySummary: UndeploySummary.NORMAL, 334 warnings: [], 335 }, 336 }, 337 expectedNumOfTeams: 0, 338 }, 339 ]; 340 341 describe.each(data)(`Renders an Application Card`, (testcase) => { 342 it(testcase.name, () => { 343 // given 344 UpdateOverview.set({ applications: testcase.applications }); 345 // when 346 const numOfTeams = renderHook(() => useApplicationsFilteredAndSorted(testcase.selectedTeams, false, '')) 347 .result.current.length; 348 expect(numOfTeams).toStrictEqual(testcase.expectedNumOfTeams); 349 }); 350 }); 351 }); 352 353 describe('Application Filter', () => { 354 interface dataT { 355 name: string; 356 query: string; 357 applications: string[]; 358 expectedLocks: number; 359 } 360 361 const data: dataT[] = [ 362 { 363 name: 'filter applications - 1 result', 364 applications: ['dummy', 'test', 'test2', 'foo'], 365 query: 'dummy', 366 expectedLocks: 1, 367 }, 368 { 369 name: 'filter applications - 0 results', 370 applications: ['dummy', 'test', 'test2'], 371 query: 'foo', 372 expectedLocks: 0, 373 }, 374 { 375 name: 'filter applications - 2 results', 376 applications: ['dummy', 'test', 'test2'], 377 query: 'test', 378 expectedLocks: 2, 379 }, 380 ]; 381 382 describe.each(data)(`Renders an Application Card`, (testcase) => { 383 it(testcase.name, () => { 384 // when 385 const nrLocks = testcase.applications.filter((val) => searchCustomFilter(testcase.query, val)).length; 386 expect(nrLocks).toStrictEqual(testcase.expectedLocks); 387 }); 388 }); 389 });