github.com/freiheit-com/kuberpult@v1.24.2-0.20240328135542-315d5630abe6/services/frontend-service/src/ui/components/ReleaseCard/ReleaseCard.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 { ReleaseCard, ReleaseCardProps } from './ReleaseCard';
    17  import { render } from '@testing-library/react';
    18  import { UpdateOverview, UpdateRolloutStatus } from '../../utils/store';
    19  import { MemoryRouter } from 'react-router-dom';
    20  import {
    21      Environment,
    22      EnvironmentGroup,
    23      Priority,
    24      Release,
    25      RolloutStatus,
    26      StreamStatusResponse,
    27      UndeploySummary,
    28  } from '../../../api/api';
    29  import { Spy } from 'spy4js';
    30  
    31  const mock_FormattedDate = Spy.mockModule('../FormattedDate/FormattedDate', 'FormattedDate');
    32  
    33  describe('Release Card', () => {
    34      const getNode = (overrides: ReleaseCardProps) => (
    35          <MemoryRouter>
    36              <ReleaseCard {...overrides} />
    37          </MemoryRouter>
    38      );
    39      const getWrapper = (overrides: ReleaseCardProps) => render(getNode(overrides));
    40  
    41      type TestData = {
    42          name: string;
    43          props: {
    44              app: string;
    45              version: number;
    46          };
    47          rels: Release[];
    48          environments: { [key: string]: Environment };
    49      };
    50      const data: TestData[] = [
    51          {
    52              name: 'using a sample release - useRelease hook',
    53              props: { app: 'test1', version: 2 },
    54              rels: [
    55                  {
    56                      version: 2,
    57                      sourceMessage: 'test-rel',
    58                      undeployVersion: false,
    59                      sourceCommitId: 'commit123',
    60                      sourceAuthor: 'author',
    61                      prNumber: '666',
    62                      createdAt: new Date(2023, 6, 6),
    63                      displayVersion: '2',
    64                  },
    65              ],
    66              environments: {},
    67          },
    68          {
    69              name: 'using a full release - component test',
    70              props: { app: 'test2', version: 2 },
    71              rels: [
    72                  {
    73                      undeployVersion: false,
    74                      version: 2,
    75                      sourceMessage: 'test-rel',
    76                      sourceCommitId: '12s3',
    77                      sourceAuthor: 'test-author',
    78                      prNumber: '666',
    79                      createdAt: new Date(2002),
    80                      displayVersion: '2',
    81                  },
    82              ],
    83              environments: {},
    84          },
    85          {
    86              name: 'using a deployed release - useDeployedAt test',
    87              props: { app: 'test2', version: 2 },
    88              rels: [
    89                  {
    90                      version: 2,
    91                      sourceMessage: 'test-rel',
    92                      sourceCommitId: 'commit123',
    93                      sourceAuthor: 'test-author',
    94                      prNumber: '666',
    95                      undeployVersion: false,
    96                      createdAt: new Date(2023, 6, 6),
    97                      displayVersion: '2',
    98                  },
    99              ],
   100              environments: {
   101                  foo: {
   102                      name: 'foo',
   103                      locks: {},
   104                      distanceToUpstream: 0,
   105                      priority: 0,
   106                      applications: {
   107                          test2: {
   108                              version: 2,
   109                              queuedVersion: 0,
   110                              name: 'test2',
   111                              locks: {},
   112                              undeployVersion: false,
   113                          },
   114                      },
   115                  },
   116              },
   117          },
   118          {
   119              name: 'using an undeployed release - useDeployedAt test',
   120              props: { app: 'test2', version: 2 },
   121              rels: [
   122                  {
   123                      version: 2,
   124                      sourceMessage: 'test-rel',
   125                      sourceCommitId: 'commit123',
   126                      undeployVersion: false,
   127                      createdAt: new Date(2023, 6, 6),
   128                      sourceAuthor: 'test-author',
   129                      prNumber: '666',
   130                      displayVersion: '2',
   131                  },
   132              ],
   133              environments: {
   134                  undeployed: {
   135                      name: 'undeployed',
   136                      locks: {},
   137                      distanceToUpstream: 0,
   138                      priority: 0,
   139                      applications: {
   140                          test2: {
   141                              version: 3,
   142                              queuedVersion: 0,
   143                              name: 'test2',
   144                              locks: {},
   145                              undeployVersion: false,
   146                          },
   147                      },
   148                  },
   149              },
   150          },
   151          {
   152              name: 'using another environment - useDeployedAt test',
   153              props: { app: 'test2', version: 2 },
   154              rels: [
   155                  {
   156                      version: 2,
   157                      sourceMessage: 'test-rel',
   158                      sourceCommitId: 'commit123',
   159                      undeployVersion: false,
   160                      sourceAuthor: 'test-author',
   161                      prNumber: '666',
   162                      createdAt: new Date(2023, 6, 6),
   163                      displayVersion: '2',
   164                  },
   165              ],
   166              environments: {
   167                  other: {
   168                      locks: {},
   169                      distanceToUpstream: 0,
   170                      priority: 0,
   171                      name: 'other',
   172                      applications: {
   173                          test3: {
   174                              version: 3,
   175                              queuedVersion: 0,
   176                              name: 'test2',
   177                              locks: {},
   178                              undeployVersion: false,
   179                          },
   180                      },
   181                  },
   182              },
   183          },
   184      ];
   185  
   186      describe.each(data)(`Renders a Release Card`, (testcase) => {
   187          it(testcase.name, () => {
   188              // given
   189              mock_FormattedDate.FormattedDate.returns(<div>some formatted date</div>);
   190              // when
   191              UpdateOverview.set({
   192                  applications: {
   193                      [testcase.props.app]: {
   194                          name: testcase.props.app,
   195                          releases: testcase.rels,
   196                          sourceRepoUrl: 'url',
   197                          undeploySummary: UndeploySummary.NORMAL,
   198                          team: 'no-team',
   199                          warnings: [],
   200                      },
   201                  },
   202                  environmentGroups: [],
   203              });
   204              const { container } = getWrapper(testcase.props);
   205  
   206              // then
   207              if (testcase.rels[0].undeployVersion) {
   208                  expect(container.querySelector('.release__title')?.textContent).toContain('Undeploy Version');
   209              } else {
   210                  expect(container.querySelector('.release__title')?.textContent).toContain(
   211                      testcase.rels[0].sourceMessage
   212                  );
   213              }
   214  
   215              if (testcase.rels[0].displayVersion) {
   216                  expect(container.querySelector('.release-version__display-version')?.textContent).toContain(
   217                      testcase.rels[0].displayVersion
   218                  );
   219              } else if (testcase.rels[0].sourceCommitId) {
   220                  expect(container.querySelector('.release-version__commit-id')?.textContent).toContain(
   221                      testcase.rels[0].sourceCommitId
   222                  );
   223              }
   224              expect(container.querySelector('.env-group-chip-list-test')).not.toBeEmptyDOMElement();
   225              expect(container.querySelector('.release__status')).toBeNull();
   226          });
   227      });
   228  });
   229  
   230  describe('Release Card Rollout Status', () => {
   231      const getNode = (overrides: ReleaseCardProps) => (
   232          <MemoryRouter>
   233              <ReleaseCard {...overrides} />
   234          </MemoryRouter>
   235      );
   236      const getWrapper = (overrides: ReleaseCardProps) => render(getNode(overrides));
   237  
   238      type TestData = {
   239          name: string;
   240          props: {
   241              app: string;
   242              version: number;
   243          };
   244          rels: Release[];
   245          environmentGroups: EnvironmentGroup[];
   246          rolloutStatus: StreamStatusResponse[];
   247          expectedStatusIcon: RolloutStatus;
   248          expectedRolloutDetails: { [name: string]: RolloutStatus };
   249      };
   250      const data: TestData[] = [
   251          {
   252              name: 'shows success when it is deployed',
   253              props: { app: 'test1', version: 2 },
   254              rels: [
   255                  {
   256                      version: 2,
   257                      sourceMessage: 'test-rel',
   258                      undeployVersion: false,
   259                      sourceCommitId: 'commit123',
   260                      sourceAuthor: 'author',
   261                      prNumber: '666',
   262                      createdAt: new Date(2023, 6, 6),
   263                      displayVersion: '2',
   264                  },
   265              ],
   266              environmentGroups: [
   267                  {
   268                      environmentGroupName: 'dev',
   269                      environments: [
   270                          {
   271                              name: 'development',
   272                              applications: {
   273                                  test1: {
   274                                      version: 2,
   275                                      name: '',
   276                                      locks: {},
   277                                      queuedVersion: 0,
   278                                      undeployVersion: false,
   279                                  },
   280                              },
   281                              locks: {},
   282                              distanceToUpstream: 0,
   283                              priority: Priority.OTHER,
   284                          },
   285                          {
   286                              name: 'development2',
   287                              applications: {
   288                                  test1: {
   289                                      version: 2,
   290                                      name: '',
   291                                      locks: {},
   292                                      queuedVersion: 0,
   293                                      undeployVersion: false,
   294                                  },
   295                              },
   296                              locks: {},
   297                              distanceToUpstream: 0,
   298                              priority: Priority.OTHER,
   299                          },
   300                      ],
   301                      priority: Priority.UNRECOGNIZED,
   302                      distanceToUpstream: 0,
   303                  },
   304                  {
   305                      environmentGroupName: 'staging',
   306                      environments: [
   307                          {
   308                              name: 'staging',
   309                              applications: {
   310                                  test1: {
   311                                      version: 2,
   312                                      name: '',
   313                                      locks: {},
   314                                      queuedVersion: 0,
   315                                      undeployVersion: false,
   316                                  },
   317                              },
   318                              locks: {},
   319                              distanceToUpstream: 0,
   320                              priority: Priority.OTHER,
   321                          },
   322                      ],
   323                      priority: Priority.UNRECOGNIZED,
   324                      distanceToUpstream: 0,
   325                  },
   326              ],
   327              rolloutStatus: [
   328                  {
   329                      environment: 'development',
   330                      application: 'test1',
   331                      version: 2,
   332                      rolloutStatus: RolloutStatus.ROLLOUT_STATUS_SUCCESFUL,
   333                  },
   334                  {
   335                      environment: 'development2',
   336                      application: 'test1',
   337                      version: 2,
   338                      rolloutStatus: RolloutStatus.ROLLOUT_STATUS_SUCCESFUL,
   339                  },
   340                  {
   341                      environment: 'staging',
   342                      application: 'test1',
   343                      version: 2,
   344                      rolloutStatus: RolloutStatus.ROLLOUT_STATUS_SUCCESFUL,
   345                  },
   346              ],
   347  
   348              expectedStatusIcon: RolloutStatus.ROLLOUT_STATUS_SUCCESFUL,
   349              expectedRolloutDetails: {
   350                  dev: RolloutStatus.ROLLOUT_STATUS_SUCCESFUL,
   351                  staging: RolloutStatus.ROLLOUT_STATUS_SUCCESFUL,
   352              },
   353          },
   354      ];
   355  
   356      describe.each(data)(`Renders a Release Card`, (testcase) => {
   357          it(testcase.name, () => {
   358              // given
   359              mock_FormattedDate.FormattedDate.returns(<div>some formatted date</div>);
   360              // when
   361              UpdateOverview.set({
   362                  applications: {
   363                      [testcase.props.app]: {
   364                          name: testcase.props.app,
   365                          releases: testcase.rels,
   366                          sourceRepoUrl: 'url',
   367                          undeploySummary: UndeploySummary.NORMAL,
   368                          team: 'no-team',
   369                          warnings: [],
   370                      },
   371                  },
   372                  environmentGroups: testcase.environmentGroups,
   373              });
   374              testcase.rolloutStatus.forEach(UpdateRolloutStatus);
   375              const { container } = getWrapper(testcase.props);
   376              // then
   377              expect(container.querySelector('.release__status')).not.toBeNull();
   378              expect(
   379                  container.querySelector(
   380                      `.release__status .rollout__icon_${rolloutStatusName(testcase.expectedStatusIcon)}`
   381                  )
   382              ).not.toBeNull();
   383              for (const [envGroup, status] of Object.entries(testcase.expectedRolloutDetails)) {
   384                  const row = container.querySelector(`tr[key="${envGroup}"]`);
   385                  expect(row?.querySelector(`.rollout__description_${rolloutStatusName(status)}`)).not.toBeNull();
   386              }
   387          });
   388      });
   389  });
   390  
   391  const rolloutStatusName = (status: RolloutStatus): string => {
   392      switch (status) {
   393          case RolloutStatus.ROLLOUT_STATUS_SUCCESFUL:
   394              return 'successful';
   395          case RolloutStatus.ROLLOUT_STATUS_PROGRESSING:
   396              return 'progressing';
   397          case RolloutStatus.ROLLOUT_STATUS_PENDING:
   398              return 'pending';
   399          case RolloutStatus.ROLLOUT_STATUS_ERROR:
   400              return 'error';
   401          case RolloutStatus.ROLLOUT_STATUS_UNHEALTHY:
   402              return 'unhealthy';
   403          default:
   404              return 'unknown';
   405      }
   406  };