Skip to content

Commit

Permalink
feat(ui): Visualize failed Esls in a new page (#1775)
Browse files Browse the repository at this point in the history
Ref: SRX-KVKLG5

---------

Co-authored-by: Sven Urbanski <[email protected]>
  • Loading branch information
AminSlk and sven-urbanski-freiheit-com authored Jul 23, 2024
1 parent 9fcddc9 commit 08144fe
Show file tree
Hide file tree
Showing 10 changed files with 654 additions and 0 deletions.
2 changes: 2 additions & 0 deletions services/frontend-service/src/assets/_components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Copyright freiheit.com*/
@import 'src/ui/components/SideBar/SideBar';
@import 'src/ui/components/snackbar/snackbar';
@import 'src/ui/Pages/CommitInfo/CommitInfoPage';
@import 'src/ui/Pages/EslWarnings/EslWarningsPage';
@import 'src/ui/components/ServiceLane/ServiceLane';
@import 'src/ui/components/ServiceLane/DotsMenu';
@import 'src/ui/components/ServiceLane/Warnings';
Expand All @@ -45,5 +46,6 @@ Copyright freiheit.com*/
@import 'src/ui/components/RolloutStatusDescription/RolloutStatusDescription';
@import 'src/ui/components/EnvironmentConfigDialog/EnvironmentConfigDialog';
@import 'src/ui/components/CommitInfo/CommitInfo';
@import 'src/ui/components/EslWarnings/EslWarnings';
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
@import url('https://fonts.googleapis.com/icon?family=Inter');
5 changes: 5 additions & 0 deletions services/frontend-service/src/ui/App/PageRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { Routes as ReactRoutes, Route, Navigate } from 'react-router-dom';
import { ProductVersionPage } from '../Pages/ProductVersion/ProductVersionPage';
import { CommitInfoPage } from '../Pages/CommitInfo/CommitInfoPage';
import { ReleaseTrainPage } from '../Pages/ReleaseTrain/ReleaseTrainPage';
import { EslWarningsPage } from '../Pages/EslWarnings/EslWarningsPage';

const routes = [
{
Expand Down Expand Up @@ -55,6 +56,10 @@ const routes = [
path: `/ui/commits/`,
element: <CommitInfoPage />,
},
{
path: `/ui/failedEvents`,
element: <EslWarningsPage />,
},
{
path: `/*`,
element: <Navigate replace to="/ui/home" />,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*This file is part of kuberpult.
Kuberpult is free software: you can redistribute it and/or modify
it under the terms of the Expat(MIT) License as published by
the Free Software Foundation.
Kuberpult is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MIT License for more details.
You should have received a copy of the MIT License
along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>.
Copyright freiheit.com*/

.esl-warnings-page {
table {
table-layout: auto;
width: 50%;

td {
padding: 4px;
}
}
.esl-warnings-page-message span {
margin-left: 10px;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/*This file is part of kuberpult.
Kuberpult is free software: you can redistribute it and/or modify
it under the terms of the Expat(MIT) License as published by
the Free Software Foundation.
Kuberpult is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MIT License for more details.
You should have received a copy of the MIT License
along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>.
Copyright freiheit.com*/

import { render } from '@testing-library/react';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { EslWarningsPage } from './EslWarningsPage';
import { fakeLoadEverything, enableDexAuth } from '../../../setupTests';
import { FailedEslsState, updateFailedEsls } from '../../utils/store';
import { GetFailedEslsResponse } from '../../../api/api';

describe('Esl Warnings page tests', () => {
type TestCase = {
name: string;
fakeLoadEverything: boolean;
enableDex: boolean;
enableDexValidToken: boolean;
failedEslsStoreData:
| {
failedEslsReady: FailedEslsState;
response: GetFailedEslsResponse | undefined;
}
| undefined;
expectedSpinnerCount: number;
expectedMainContentCount: number;
expectedText: string;
expectedNumLoginPage: number;
};

const testCases: TestCase[] = [
{
name: 'A loading spinner renders when the page is still loading',
fakeLoadEverything: false,
enableDex: false,
enableDexValidToken: false,
expectedSpinnerCount: 1,
expectedMainContentCount: 0,
expectedText: 'Loading Configuration',
failedEslsStoreData: {
failedEslsReady: FailedEslsState.LOADING,
response: undefined,
},
expectedNumLoginPage: 0,
},
{
name: 'A spinner is shown when waiting for the server to respond',
fakeLoadEverything: true,
enableDex: false,
enableDexValidToken: false,
expectedSpinnerCount: 1,
expectedMainContentCount: 0,
expectedText: 'Loading Failed Esls info',
failedEslsStoreData: {
failedEslsReady: FailedEslsState.LOADING,
response: undefined,
},
expectedNumLoginPage: 0,
},
{
name: 'An error message is shown when the backend returns an error',
fakeLoadEverything: true,
enableDex: false,
enableDexValidToken: false,
expectedSpinnerCount: 0,
expectedMainContentCount: 1,
expectedText: 'Backend error',
failedEslsStoreData: {
response: undefined,
failedEslsReady: FailedEslsState.ERROR,
},
expectedNumLoginPage: 0,
},
{
name: 'An error message is shown when the backend returns a not found status',
fakeLoadEverything: true,
enableDex: false,
enableDexValidToken: false,
expectedSpinnerCount: 0,
expectedMainContentCount: 1,
expectedText: 'All events were processed successfully',
failedEslsStoreData: {
response: undefined,
failedEslsReady: FailedEslsState.NOTFOUND,
},
expectedNumLoginPage: 0,
},
{
name: 'Some main content exists when the page is done loading',
fakeLoadEverything: true,
enableDex: false,
enableDexValidToken: false,
expectedSpinnerCount: 0,
expectedMainContentCount: 1,
expectedText:
'Failed ESL Event List: This page shows all events that could not be processed, and therefore were never written to the manifest repo. Any operation in kuberpult is an event, like creating a lock or running a release',
failedEslsStoreData: {
failedEslsReady: FailedEslsState.READY,
response: {
failedEsls: [
{
eslVersion: 1,
createdAt: new Date('2024-02-09T11:20:00Z'),
eventType: 'EvtCreateApplicationVersion',
json: '{"version": 1, "app": "test-app-name"}',
},
],
},
},
expectedNumLoginPage: 0,
},
{
name: 'A login page renders when Dex is enabled',
fakeLoadEverything: true,
enableDex: true,
enableDexValidToken: false,
expectedSpinnerCount: 0,
expectedMainContentCount: 0,
expectedText: 'Log in to Dex',
failedEslsStoreData: {
failedEslsReady: FailedEslsState.LOADING,
response: undefined,
},
expectedNumLoginPage: 1,
},
{
name: 'Some main content exists when Dex is enabled and the token is valid',
fakeLoadEverything: true,
enableDex: true,
enableDexValidToken: true,
expectedSpinnerCount: 0,
expectedMainContentCount: 1,
expectedText:
'Failed ESL Event List: This page shows all events that could not be processed, and therefore were never written to the manifest repo. Any operation in kuberpult is an event, like creating a lock or running a release',
failedEslsStoreData: {
failedEslsReady: FailedEslsState.READY,
response: {
failedEsls: [
{
eslVersion: 1,
createdAt: new Date('2024-02-09T11:20:00Z'),
eventType: 'EvtCreateApplicationVersion',
json: '{"version": 1, "app": "test-app-name"}',
},
],
},
},
expectedNumLoginPage: 0,
},
];
describe.each(testCases)('', (tc) => {
test(tc.name, () => {
fakeLoadEverything(tc.fakeLoadEverything);
if (tc.failedEslsStoreData !== undefined) updateFailedEsls.set(tc.failedEslsStoreData);
if (tc.enableDex) {
enableDexAuth(tc.enableDexValidToken);
}

const { container } = render(
<MemoryRouter initialEntries={['/ui/eslWarnings/']}>
<Routes>
<Route path={'/ui/eslWarnings/'} element={<EslWarningsPage />} />
</Routes>
</MemoryRouter>
);

expect(container.getElementsByClassName('spinner')).toHaveLength(tc.expectedSpinnerCount);
expect(container.getElementsByClassName('main-content esl-warnings-page')).toHaveLength(
tc.expectedMainContentCount
);
expect(
container.getElementsByClassName('button-main env-card-deploy-btn mdc-button--unelevated')
).toHaveLength(tc.expectedNumLoginPage);
expect(container.textContent).toContain(tc.expectedText);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*This file is part of kuberpult.
Kuberpult is free software: you can redistribute it and/or modify
it under the terms of the Expat(MIT) License as published by
the Free Software Foundation.
Kuberpult is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MIT License for more details.
You should have received a copy of the MIT License
along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>.
Copyright freiheit.com*/

import { getFailedEsls, useFailedEsls, useGlobalLoadingState, FailedEslsState } from '../../utils/store';
import { TopAppBar } from '../../components/TopAppBar/TopAppBar';
import { Spinner } from '../../components/Spinner/Spinner';
import React from 'react';
import { EslWarnings } from '../../components/EslWarnings/EslWarnings';
import { useAzureAuthSub } from '../../utils/AzureAuthProvider';

export const EslWarningsPage: React.FC = () => {
const { authHeader } = useAzureAuthSub((auth) => auth);

React.useEffect(() => {
getFailedEsls(authHeader);
}, [authHeader]);

const failedEsls = useFailedEsls((res) => res);

const element = useGlobalLoadingState();
if (element) {
return element;
}

switch (failedEsls.failedEslsReady) {
case FailedEslsState.LOADING:
return <Spinner message="Loading Failed Esls info" />;
case FailedEslsState.ERROR:
return (
<div>
<TopAppBar showAppFilter={false} showTeamFilter={false} showWarningFilter={false} />
<main className="main-content esl-warnings-page">Backend error</main>
</div>
);
case FailedEslsState.NOTFOUND:
return (
<div>
<main className="main-content esl-warnings-page">
<p>All events were processed successfully</p>
</main>
</div>
);
case FailedEslsState.READY:
return <EslWarnings failedEsls={failedEsls.response} />;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*This file is part of kuberpult.
Kuberpult is free software: you can redistribute it and/or modify
it under the terms of the Expat(MIT) License as published by
the Free Software Foundation.
Kuberpult is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MIT License for more details.
You should have received a copy of the MIT License
along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>.
Copyright freiheit.com*/

.esl-warnings-page {
table,
th,
td {
border: 1px solid var(--mdc-theme-primary);
border-collapse: collapse;
}

table {
width: 100%;
}

.esls {
th.date {
width: 25%;
}

th.description {
width: 50%;
}

th.environments {
width: 25%;
}
}
.select-timezone {
margin-bottom: 10px;
}
}
Loading

0 comments on commit 08144fe

Please sign in to comment.