Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(snapshot): add test pipelinerun list and capitalize breadcrumbs #847

Merged
merged 3 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8329,6 +8329,33 @@ export const MockEnvironments = [
},
];

export const MockEnvironmentsWithoutDisplayName = [
{
apiVersion: 'appstudio.redhat.com/v1alpha1',
kind: 'Environment',
metadata: {
annotations: {
'toolchain.dev.openshift.com/last-applied-configuration':
'{"apiVersion":"appstudio.redhat.com/v1alpha1","kind":"Environment","metadata":{"labels":{"toolchain.dev.openshift.com/owner":"jephilli","toolchain.dev.openshift.com/provider":"codeready-toolchain"},"name":"development","namespace":"jephilli-tenant"},"spec":{"deploymentStrategy":"AppStudioAutomated","displayName":"Development","type":"Non-POC"}}',
},
resourceVersion: '14576436',
name: 'test',
uid: '68aea4ae-d422-4f73-8baa-9a1f5d8eaee7',
creationTimestamp: '2023-03-01T11:47:57Z',
generation: 1,
namespace: 'jephilli-tenant',
labels: {
'toolchain.dev.openshift.com/owner': 'jephilli',
'toolchain.dev.openshift.com/provider': 'codeready-toolchain',
},
},
spec: {
deploymentStrategy: 'AppStudioAutomated',
type: 'Non-POC',
},
},
];

export const MockSnapshotsEB = [
{
apiVersion: 'appstudio.redhat.com/v1alpha1',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ interface EnvironmentProvisionErrorAlertProps {
const EnvironmentProvisionErrorAlert: React.FC<EnvironmentProvisionErrorAlertProps> = ({
errorStatus,
}) => {
if (!Array.isArray(errorStatus) || errorStatus.length === 0) {
return null;
}
const title = (
<>
Failed for{' '}
Expand Down Expand Up @@ -39,7 +42,7 @@ const EnvironmentProvisionErrorAlert: React.FC<EnvironmentProvisionErrorAlertPro
timestamp={errorStatus[0].lastUpdateTime}
data-test="alert-timestamp"
/>
<ExpandableSection toggleText="Show details">
<ExpandableSection toggleText="Show details" data-test="error-expandable-section">
{errorStatus.map((s, i) => (
<span key={s.scenario}>
{i > 0 && ', '}
Expand Down
13 changes: 8 additions & 5 deletions src/components/SnapshotDetails/SnapshotDetailsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import { LoadingBox } from '../../shared/components/status-box/StatusBox';
import { Timestamp } from '../../shared/components/timestamp/Timestamp';
import { HttpError } from '../../shared/utils/error/http-error';
import { EnvironmentKind } from '../../types';
import { Snapshot, SnapshotEnvironmentBinding } from '../../types/coreBuildService';
import { useApplicationBreadcrumbs } from '../../utils/breadcrumb-utils';
import { createCommitObjectFromPLR } from '../../utils/commits-utils';
Expand Down Expand Up @@ -63,7 +64,7 @@
isList: true,
});

const deployedEnvironments = React.useMemo(() => {
const deployedEnvironments: EnvironmentKind[] = React.useMemo(() => {
const envList = [];
sebLoaded &&
!sebLoadError &&
Expand All @@ -76,7 +77,7 @@
seb.spec?.snapshot === snapshot?.metadata?.name,
);
if (snapshotWithEnvironment) {
envList.push(env?.metadata.name);
envList.push(env);

Check warning on line 80 in src/components/SnapshotDetails/SnapshotDetailsView.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/SnapshotDetails/SnapshotDetailsView.tsx#L80

Added line #L80 was not covered by tests
}
});
return envList;
Expand Down Expand Up @@ -112,7 +113,7 @@
...applicationBreadcrumbs,
{
path: `#`,
name: 'snapshots',
name: 'Snapshots',
},
{
path: `/application-pipeline/workspaces/${workspace}/applications/${applicationName}/snapshots/${snapshotName}`,
Expand Down Expand Up @@ -141,12 +142,14 @@
</Text>
<Text component={TextVariants.p} data-test="snapshot-commit-label">
{environments?.map((env) => {
const isDeployed = deployedEnvironments.includes(env.metadata?.name);
const isDeployed = deployedEnvironments.find(
(e) => e.metadata.name === env.metadata?.name,
);
return (
<>
<StatusIconWithTextLabel
key={env.metadata?.name}
text={env.metadata.name}
text={env.spec.displayName ?? env.metadata.name}
dataTestAttribute="snapshot-env-label"
status={isDeployed ? runStatus.Succeeded : runStatus.Cancelling}
/>{' '}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,39 @@ import { getEnvironmentProvisionError } from '../utils/snapshot-utils';
configure({ testIdAttribute: 'data-test' });

describe('EnvironmentProvisionErrorAlert', () => {
it('should return null when no ErrorStatus', () => {
routerRenderer(<EnvironmentProvisionErrorAlert errorStatus={null} />);
expect(screen.queryByTestId(/env-provision-err-alert/)).not.toBeInTheDocument();
});

it('should return for emoty array ErrorStatus', () => {
routerRenderer(<EnvironmentProvisionErrorAlert errorStatus={[]} />);
expect(screen.queryByTestId(/env-provision-err-alert/)).not.toBeInTheDocument();
});

it('should return error section as hidden initially', () => {
routerRenderer(
<EnvironmentProvisionErrorAlert
errorStatus={getEnvironmentProvisionError(MockSnapshots[1])}
/>,
);
expect(
screen
.getByTestId('error-expandable-section')
.children[0].children[0].children[0].getAttribute('aria-hidden'),
).toBe('true');
});

it('should show relevant Error Details Alert', () => {
routerRenderer(
<EnvironmentProvisionErrorAlert
errorStatus={getEnvironmentProvisionError(MockSnapshots[1])}
/>,
);
screen.getByTestId(/env-provision-err-alert/);
screen.getByText('app-sample-go-basic-enterprise-contract');
screen.getByText(/Snapshot failed to deploy/);
screen.getByText(/Sep 19, 2023/);
expect(screen.getByTestId(/env-provision-err-alert/)).toBeInTheDocument();
expect(screen.getByText('app-sample-go-basic-enterprise-contract')).toBeInTheDocument();
expect(screen.getByText(/Snapshot failed to deploy/)).toBeInTheDocument();
expect(screen.getByText(/Sep 19, 2023/)).toBeInTheDocument();
});

it('should show multiple scenarios for multiple failures', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ import '@testing-library/jest-dom';
import { useK8sWatchResource } from '@openshift/dynamic-plugin-sdk-utils';
import { configure, screen } from '@testing-library/react';
import { WatchK8sResource } from '../../../dynamic-plugin-sdk';
import { useEnvironments } from '../../../hooks/useEnvironments';
import { PipelineRunGroupVersionKind, SnapshotGroupVersionKind } from '../../../models';
import { IntegrationTestScenarioKind } from '../../../types/coreBuildService';
import { routerRenderer } from '../../../utils/test-utils';
import { pipelineWithCommits } from '../../Commits/__data__/pipeline-with-commits';
import { useCommitStatus } from '../../Commits/commit-status';
import { MockSnapshots } from '../../Commits/CommitDetails/visualization/__data__/MockCommitWorkflowData';
import {
MockEnvironments,
MockEnvironmentsWithoutDisplayName,
MockSnapshots,
} from '../../Commits/CommitDetails/visualization/__data__/MockCommitWorkflowData';
import SnapshotDetails from '../SnapshotDetailsView';

jest.mock('@openshift/dynamic-plugin-sdk-utils', () => ({
Expand All @@ -31,6 +36,10 @@ jest.mock('react-router-dom', () => {
};
});

jest.mock('../../../hooks/useEnvironments', () => ({
useEnvironments: jest.fn(),
}));

jest.mock('../../../utils/rbac', () => ({
useAccessReviewForModel: jest.fn(() => [true, true]),
}));
Expand All @@ -39,6 +48,8 @@ const useParamsMock = useParams as jest.Mock;

const watchResourceMock = useK8sWatchResource as jest.Mock;

const mockUseEnvironments = useEnvironments as jest.Mock;

configure({ testIdAttribute: 'data-test' });

const mockSnapshots: IntegrationTestScenarioKind[] = [...MockSnapshots];
Expand All @@ -53,9 +64,20 @@ const getMockedResources = (params: WatchK8sResource) => {
return [[], true];
};

const errorSnapshotResources = (params: WatchK8sResource) => {
if (params?.groupVersionKind === SnapshotGroupVersionKind) {
return [mockSnapshots[0], true];
}
if (params?.groupVersionKind === PipelineRunGroupVersionKind) {
return [[pipelineWithCommits[0]], true];
}
return [[], true];
};

describe('SnapshotDetailsView', () => {
beforeEach(() => {
useParamsMock.mockReturnValue({ activeTab: 'overview' });
mockUseEnvironments.mockReturnValue([MockEnvironments, true]);
(useCommitStatus as jest.Mock).mockReturnValueOnce(['-', true]);
});

Expand Down Expand Up @@ -88,6 +110,45 @@ describe('SnapshotDetailsView', () => {
expect(screen.getByTestId('snapshot-name').innerHTML).toBe('my-test-output-1');
});

it('should display correct breadcrumbs', () => {
watchResourceMock.mockImplementation(getMockedResources);
routerRenderer(
<SnapshotDetails snapshotName="my-test-output-1" applicationName="my-test-output" />,
);
expect(screen.getByText(/Snapshots/)).toBeInTheDocument();
});

it('should show environment name in details', () => {
watchResourceMock.mockImplementation(getMockedResources);
mockUseEnvironments.mockReturnValue([MockEnvironmentsWithoutDisplayName, true]);
routerRenderer(
<SnapshotDetails snapshotName="my-test-output-1" applicationName="my-test-output" />,
);
expect(screen.getByText('Deployed to')).toBeInTheDocument();
expect(screen.getByText('test')).toBeInTheDocument();
});

it('should show environment display name instead of metadata', () => {
watchResourceMock.mockImplementation(getMockedResources);
mockUseEnvironments.mockReturnValue([MockEnvironments, true]);
routerRenderer(
<SnapshotDetails snapshotName="my-test-output-1" applicationName="my-test-output" />,
);
expect(screen.getByText('Deployed to')).toBeInTheDocument();
expect(screen.getByText('Development')).toBeInTheDocument();
});

it('should show environment label in header', () => {
watchResourceMock.mockImplementation(getMockedResources);
mockUseEnvironments.mockReturnValue([MockEnvironments, true]);
routerRenderer(
<SnapshotDetails snapshotName="my-test-output-1" applicationName="my-test-output" />,
);
const envLabel = screen.getByTestId('snapshot-env-label');
expect(envLabel).toBeInTheDocument();
expect(envLabel.innerHTML).toBe('Development');
});

it('should show correct details', () => {
mockSnapshots[0].metadata.deletionTimestamp = '1';
watchResourceMock.mockImplementation(getMockedResources);
Expand All @@ -99,6 +160,25 @@ describe('SnapshotDetailsView', () => {
expect(screen.getByTestId('snapshot-name').innerHTML).toBe('my-test-output-2');
});

it('should show EnvProvisionError', () => {
mockSnapshots[0].metadata.deletionTimestamp = '1';
watchResourceMock.mockImplementation(errorSnapshotResources);
routerRenderer(
<SnapshotDetails snapshotName="my-test-output-2" applicationName="my-test-output" />,
);
screen.queryByTestId('env-provision-err-alert');
screen.queryByText('Failed for app-sample-go-basic-enterprise-contract');
});

it('should show failed scenario on EnvProvisionError', () => {
mockSnapshots[0].metadata.deletionTimestamp = '1';
watchResourceMock.mockImplementation(errorSnapshotResources);
routerRenderer(
<SnapshotDetails snapshotName="my-test-output-2" applicationName="my-test-output" />,
);
screen.queryByText('scn 2');
});

it('should show pipelinerun details', () => {
useParamsMock.mockReturnValue({ activeTab: 'pipelineruns' });
mockSnapshots[0].metadata.deletionTimestamp = '1';
Expand Down
8 changes: 4 additions & 4 deletions src/components/SnapshotDetails/tabs/SnapshotOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ScanStatus } from '../../../components/PipelineRunListView/ScanStatus';
import { useScanResults } from '../../../hooks/useScanResults';
import CommitLabel from '../../../shared/components/commit-label/CommitLabel';
import { Timestamp } from '../../../shared/components/timestamp/Timestamp';
import { Commit } from '../../../types';
import { Commit, EnvironmentKind } from '../../../types';
import { Snapshot } from '../../../types/coreBuildService';
import { useWorkspaceInfo } from '../../../utils/workspace-context-utils';
import EnvironmentProvisionErrorAlert from '../EnvironmentProvisionErrorAlert';
Expand All @@ -26,7 +26,7 @@ interface SnapshotOverviewTabProps {
snapshot: Snapshot;
commit?: Commit;
buildPipelineName?: string;
environments?: string[];
environments?: EnvironmentKind[];
}

const SnapshotOverviewTab: React.FC<React.PropsWithChildren<SnapshotOverviewTabProps>> = ({
Expand Down Expand Up @@ -110,11 +110,11 @@ const SnapshotOverviewTab: React.FC<React.PropsWithChildren<SnapshotOverviewTabP
<EnvironmentProvisionErrorAlert errorStatus={errorStatus} />
) : (
environments.map((env) => (
<div key={env}>
<div key={env.metadata.name}>
<Link
to={`/application-pipeline/workspaces/${workspace}/applications/${snapshot.spec.application}/deployments`}
>
{env}
{env.spec?.displayName ?? env.metadata?.name}
</Link>
</div>
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ToolbarGroup,
ToolbarItem,
debounce,
capitalize,
} from '@patternfly/react-core';
import {
Select,
Expand Down Expand Up @@ -183,7 +184,7 @@ const SnapshotPipelineRunsList: React.FC<React.PropsWithChildren<SnapshotPipelin
isChecked={typeFilters.includes(filter)}
itemCount={statusFilterObj[filter] ?? 0}
>
{filter}
{capitalize(filter)}
</SelectOption>
))}
</SelectGroup>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ const SnapshotPipelineRunTab: React.FC<React.PropsWithChildren<SnapshotPipelineR
if (loaded && !LoadError) {
return pipelineRuns.filter(
(plr) =>
plr.metadata?.annotations &&
plr.metadata.annotations[PipelineRunLabel.SNAPSHOT] === snapshotName,
(plr.metadata?.annotations &&
plr.metadata.annotations[PipelineRunLabel.SNAPSHOT] === snapshotName) ||
(plr.metadata?.labels && plr.metadata.labels[PipelineRunLabel.SNAPSHOT] === snapshotName),
);
}
return [];
Expand Down
Loading