Skip to content

Commit

Permalink
feat: rework WorkspaceDetails page
Browse files Browse the repository at this point in the history
Signed-off-by: Oleksii Kurinnyi <[email protected]>
  • Loading branch information
akurinnoy committed Nov 17, 2023
1 parent e9762d8 commit cb364ea
Show file tree
Hide file tree
Showing 35 changed files with 1,211 additions and 652 deletions.
13 changes: 11 additions & 2 deletions packages/dashboard-frontend/src/Routes/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,17 @@ describe('Routes', () => {
expect(screen.queryByTestId('fallback-spinner')).not.toBeInTheDocument();
});

it('should handle "/workspace/namespace/name?tab=Devworkspace"', async () => {
const location = buildDetailsLocation(workspace, WorkspaceDetailsTab.DEVWORKSPACE);
it('should handle "/workspace/namespace/name?tab=Logs"', async () => {
const location = buildDetailsLocation(workspace, WorkspaceDetailsTab.LOGS);
render(getComponent(location));

await waitFor(() => expect(screen.queryByText('Workspace Details')).toBeTruthy());

expect(screen.queryByTestId('fallback-spinner')).not.toBeInTheDocument();
});

it('should handle "/workspace/namespace/name?tab=Events"', async () => {
const location = buildDetailsLocation(workspace, WorkspaceDetailsTab.EVENTS);
render(getComponent(location));

await waitFor(() => expect(screen.queryByText('Workspace Details')).toBeTruthy());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

import React from 'react';

import { Props } from '@/components/DevfileViewer';

export class DevfileViewer extends React.PureComponent<Props> {
public render(): React.ReactNode {
const { isActive, isExpanded, value } = this.props;

return (
<div>
Mock Devfile Viewer
<span data-testid="devfile-viewer-is-active">{isActive.toString()}</span>
<span data-testid="devfile-viewer-is-expanded">{isExpanded.toString()}</span>
<span data-testid="devfile-viewer-value">{value}</span>
</div>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import React from 'react';

import styles from '@/components/DevfileViewer/index.module.css';

type Props = {
export type Props = {
isActive: boolean;
isExpanded: boolean;
value: string;
Expand Down Expand Up @@ -71,5 +71,3 @@ export class DevfileViewer extends React.PureComponent<Props> {
);
}
}

export default DevfileViewer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2018-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

// mock for the EditorTools component
import React from 'react';

import { Props } from '@/components/EditorTools';

export default class EditorTools extends React.PureComponent<Props> {
public render(): React.ReactNode {
const { handleExpand } = this.props;
return (
<div>
Mock Editor Tools
<button onClick={() => handleExpand(true)}>Expand Editor</button>
</div>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { AppState } from '@/store';
import { actionCreators } from '@/store/BannerAlert';
import { selectApplications } from '@/store/ClusterInfo/selectors';

type Props = MappedProps & {
export type Props = MappedProps & {
devfileOrDevWorkspace: devfileApi.DevWorkspace | devfileApi.Devfile;
handleExpand: (isExpand: boolean) => void;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export class WorkspaceActionsProvider extends React.Component<Props, State> {
return this.handleLocation(buildIdeLoaderLocation(workspace), workspace);
}
case WorkspaceAction.WORKSPACE_DETAILS: {
return buildDetailsLocation(workspace, WorkspaceDetailsTab.DEVFILE);
return buildDetailsLocation(workspace);
}
case WorkspaceAction.START_DEBUG_AND_OPEN_LOGS: {
await this.props.startWorkspace(workspace, {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`DevfileEditorTab component snapshot 1`] = `
[
<br />,
<div
className="pf-c-content editorTab"
>
<div>
Mock Editor Tools
<button
onClick={[Function]}
>
Expand Editor
</button>
</div>
<div>
Mock Devfile Viewer
<span
data-testid="devfile-viewer-is-active"
>
true
</span>
<span
data-testid="devfile-viewer-is-expanded"
>
false
</span>
<span
data-testid="devfile-viewer-value"
>
schemaVersion: 2.2.0
metadata:
name: wksp
namespace: ''
components: []
</span>
</div>
</div>,
]
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright (c) 2018-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/

import userEvent from '@testing-library/user-event';
import { dump } from 'js-yaml';
import { cloneDeep } from 'lodash';
import React from 'react';

import { DevfileEditorTab, prepareDevfile } from '@/pages/WorkspaceDetails/DevfileEditorTab';
import getComponentRenderer, { screen } from '@/services/__mocks__/getComponentRenderer';
import devfileApi from '@/services/devfileApi';
import { constructWorkspace, Workspace } from '@/services/workspace-adapter';
import {
DEVWORKSPACE_DEVFILE,
DEVWORKSPACE_METADATA_ANNOTATION,
} from '@/services/workspace-client/devworkspace/devWorkspaceClient';
import { DevWorkspaceBuilder } from '@/store/__mocks__/devWorkspaceBuilder';

jest.mock('@/components/EditorTools');
jest.mock('@/components/DevfileViewer');

const { createSnapshot, renderComponent } = getComponentRenderer(getComponent);

describe('DevfileEditorTab', () => {
let workspace: Workspace;

beforeEach(() => {
const devWorkspace = new DevWorkspaceBuilder().withName('wksp').build();
workspace = constructWorkspace(devWorkspace);
});

describe('component', () => {
test('snapshot', () => {
const snapshot = createSnapshot(true, workspace);
expect(snapshot.toJSON()).toMatchSnapshot();
});

test('expanded state', () => {
renderComponent(true, workspace);

const buttonExpand = screen.getByRole('button', { name: 'Expand Editor' });
userEvent.click(buttonExpand);

const isExpanded = screen.getByTestId('devfile-viewer-is-expanded');
expect(isExpanded).toHaveTextContent('true');
});
});

describe('prepareDevfile', () => {
describe('devWorkspace with the DEVWORKSPACE_DEVFILE annotation', () => {
test('devfile without DEVWORKSPACE_METADATA_ANNOTATION', () => {
const expectedDevfile = {
schemaVersion: '2.1.0',
metadata: {
name: 'wksp',
namespace: 'user-che',
tags: ['tag1', 'tag2'],
},
} as devfileApi.Devfile;
const devWorkspace = new DevWorkspaceBuilder()
.withName('wksp')
.withNamespace('user-che')
.withMetadata({
annotations: {
[DEVWORKSPACE_DEVFILE]: dump(expectedDevfile),
},
})
.build();
const workspace = constructWorkspace(devWorkspace);

const devfile = prepareDevfile(workspace);
expect(devfile).toEqual(expectedDevfile);
});

test('devfile with DEVWORKSPACE_METADATA_ANNOTATION', () => {
const origDevfile = {
schemaVersion: '2.1.0',
metadata: {
name: 'wksp',
namespace: 'user-che',
tags: ['tag1', 'tag2'],
},
attributes: {
[DEVWORKSPACE_METADATA_ANNOTATION]: dump({ url: 'devfile-source-location' }),
},
} as devfileApi.Devfile;
const devWorkspace = new DevWorkspaceBuilder()
.withName('wksp')
.withNamespace('user-che')
.withMetadata({
annotations: {
[DEVWORKSPACE_DEVFILE]: dump(origDevfile),
},
})
.build();
const workspace = constructWorkspace(devWorkspace);

const devfile = prepareDevfile(workspace);

const expectedDevfile = cloneDeep(origDevfile);
delete expectedDevfile.attributes;

expect(devfile).toEqual(expectedDevfile);
});
});

test('devWorkspace without DEVWORKSPACE_DEVFILE annotation', () => {
const expectedDevfile = {
schemaVersion: '2.2.0',
metadata: {
name: 'wksp',
namespace: 'user-che',
},
components: [],
} as devfileApi.Devfile;
const devWorkspace = new DevWorkspaceBuilder()
.withName('wksp')
.withNamespace('user-che')
.build();
const workspace = constructWorkspace(devWorkspace);

const devfile = prepareDevfile(workspace);
expect(devfile).toEqual(expectedDevfile);
});
});
});

function getComponent(isActive: boolean, workspace: Workspace) {
return <DevfileEditorTab isActive={isActive} workspace={workspace} />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { TextContent } from '@patternfly/react-core';
import { load } from 'js-yaml';
import React from 'react';

import DevfileViewer from '@/components/DevfileViewer';
import { DevfileViewer } from '@/components/DevfileViewer';
import EditorTools from '@/components/EditorTools';
import styles from '@/pages/WorkspaceDetails/DevfileEditorTab/index.module.css';
import { DevfileAdapter } from '@/services/devfile/adapter';
Expand Down Expand Up @@ -49,20 +49,8 @@ export class DevfileEditorTab extends React.PureComponent<Props, State> {
const { isExpanded } = this.state;
const editorTabStyle = isExpanded ? styles.editorTabExpanded : styles.editorTab;

let originDevfileStr = this.props.workspace.ref.metadata?.annotations?.[DEVWORKSPACE_DEVFILE];
if (!originDevfileStr) {
originDevfileStr = stringify(this.props.workspace.devfile);
}
const devfile = load(originDevfileStr) as devfileApi.Devfile;
const attrs = DevfileAdapter.getAttributesFromDevfileV2(devfile);
if (attrs?.[DEVWORKSPACE_METADATA_ANNOTATION]) {
delete attrs[DEVWORKSPACE_METADATA_ANNOTATION];
if (Object.keys(attrs).length === 0) {
delete devfile.attributes;
delete devfile.metadata.attributes;
}
originDevfileStr = stringify(devfile);
}
const devfile = prepareDevfile(this.props.workspace);
const devfileStr = stringify(devfile);

return (
<React.Fragment>
Expand All @@ -77,7 +65,7 @@ export class DevfileEditorTab extends React.PureComponent<Props, State> {
<DevfileViewer
isActive={this.props.isActive}
isExpanded={isExpanded}
value={originDevfileStr}
value={devfileStr}
id="devfileViewerId"
/>
</TextContent>
Expand All @@ -86,4 +74,18 @@ export class DevfileEditorTab extends React.PureComponent<Props, State> {
}
}

export default DevfileEditorTab;
export function prepareDevfile(workspace: Workspace): devfileApi.Devfile {
const devfileStr = workspace.ref.metadata?.annotations?.[DEVWORKSPACE_DEVFILE];
const devfile = devfileStr ? (load(devfileStr) as devfileApi.Devfile) : workspace.devfile;

const attrs = DevfileAdapter.getAttributesFromDevfileV2(devfile);
if (attrs?.[DEVWORKSPACE_METADATA_ANNOTATION]) {
delete attrs[DEVWORKSPACE_METADATA_ANNOTATION];
}
if (Object.keys(attrs).length === 0) {
delete devfile.attributes;
delete devfile.metadata.attributes;
}

return devfile;
}

This file was deleted.

Loading

0 comments on commit cb364ea

Please sign in to comment.