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

Remove redundant loader #142

Merged
merged 4 commits into from
Feb 1, 2021
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
23 changes: 14 additions & 9 deletions license-tool/src/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
#!/bin/bash

# Validate yarn.lock
if [ -f yarn.lock ]; then
node dash-licenses/yarn/index.js | \
java -jar dash-licenses/target/org.eclipse.dash.licenses-0.0.1-SNAPSHOT.jar -
echo "The DEPENDENCIES file is being generated..."
node ./bump-deps.js
echo "Done."
else
echo "The yarn.lock file is not present!!!"
if [ ! -f yarn.lock ]; then
echo "Can't find yarn.lock. Generate lock file and try again."
exit 1
fi

DASH_LICENSES=dash-licenses/core/target/org.eclipse.dash.licenses-0.0.1-SNAPSHOT.jar
if [ ! -f $DASH_LICENSES ]; then
echo "Can't find org.eclipse.dash.licenses-0.0.1-SNAPSHOT.jar. Rebuild 'nodejs-license-tool' image and try again."
exit 1
fi

node dash-licenses/yarn/index.js | java -jar $DASH_LICENSES -
echo "The DEPENDENCIES file is being generated..."
node ./bump-deps.js
echo "Done."
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
},
"dependencies": {
"@eclipse-che/workspace-client": "^0.0.1-1608729566",
"@patternfly/patternfly": "^4.10.31",
"@patternfly/react-core": "~4.84.4",
"@patternfly/react-icons": "^4.3.5",
"@patternfly/react-table": "^4.5.7",
Expand Down
1 change: 1 addition & 0 deletions src/Layout/Navigation/__tests__/RecentList.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ function createFakeStore(workspaces: che.Workspace[]): Store {
devfileRegistries: {} as any,
user: {} as any,
infrastructureNamespace: {} as any,
environment: {} as any,
userPreferences: {} as any,
};
const middleware = [thunk];
Expand Down
76 changes: 57 additions & 19 deletions src/containers/IdeLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import { RouteComponentProps } from 'react-router';
import { lazyInject } from '../inversify.config';
import IdeLoader, { AlertOptions } from '../pages/IdeLoader';
import { Debounce } from '../services/helpers/debounce';
import { delay } from '../services/helpers/delay';
import { IdeLoaderTab, WorkspaceStatus } from '../services/helpers/types';
import { AppState } from '../store';
import { selectIsDevelopment } from '../store/Environment/selectors';
import * as WorkspaceStore from '../store/Workspaces';
import { selectAllWorkspaces, selectLogs, selectWorkspaceById } from '../store/Workspaces/selectors';

Expand All @@ -41,7 +43,7 @@ type State = {
currentStep: LoadIdeSteps;
preselectedTabKey?: IdeLoaderTab;
ideUrl?: string;
hasError?: boolean;
hasError: boolean;
};

class IdeLoaderContainer extends React.PureComponent<Props, State> {
Expand Down Expand Up @@ -131,8 +133,7 @@ class IdeLoaderContainer extends React.PureComponent<Props, State> {
const workspace = allWorkspaces.find(workspace =>
workspace.namespace === this.state.namespace && workspace.devfile.metadata.name === this.state.workspaceName);
if (workspace && workspace.runtime && workspace.status === WorkspaceStatus[WorkspaceStatus.RUNNING]) {
this.updateIdeUrl(workspace.runtime);
return;
return await this.updateIdeUrl(workspace.runtime);
} else if (workspace && workspace.status == WorkspaceStatus[WorkspaceStatus.ERROR]) {
this.showErrorAlert(workspace);
}
Expand All @@ -150,21 +151,47 @@ class IdeLoaderContainer extends React.PureComponent<Props, State> {
});
}

public async componentDidUpdate(prevProps: Props, prevState: Props): Promise<void> {
public async componentDidUpdate(prevProps: Props, prevState: State): Promise<void> {
const { allWorkspaces, match: { params } } = this.props;
const { hasError } = this.state;
const workspace = allWorkspaces.find(workspace =>
workspace.namespace === params.namespace && workspace.devfile.metadata.name === this.workspaceName);
if (workspace && ((prevState.workspaceName === this.workspaceName) && !hasError) && workspace.status === WorkspaceStatus[WorkspaceStatus.ERROR]) {
// When the current workspace didn't have an error but now does then show it
this.showErrorAlert(workspace);
} else if (workspace && (prevState.workspaceName !== this.workspaceName) && workspace.status === WorkspaceStatus[WorkspaceStatus.ERROR]) {
// When the clicked workspace changes and the new one errors then show the new error message
this.setState({ hasError: true, workspaceName: this.workspaceName, currentStep: LoadIdeSteps.START_WORKSPACE, workspaceId: workspace.id });
this.showErrorAlert(workspace);
workspace.namespace === params.namespace
&& workspace.devfile.metadata.name === this.workspaceName);
if (!workspace) {
const alertOptions = {
title: `Workspace "${this.workspaceName}" is not found.`,
alertVariant: AlertVariant.danger,
};
if (this.loadFactoryPageCallbacks.showAlert) {
this.loadFactoryPageCallbacks.showAlert(alertOptions);
} else {
console.error(alertOptions.title);
}
this.setState({
hasError: true,
});
} else if (workspace.status === WorkspaceStatus[WorkspaceStatus.ERROR]) {
if ((prevState.workspaceName === this.workspaceName) && !hasError) {
// When the current workspace didn't have an error but now does then show it
this.showErrorAlert(workspace);
} else if ((prevState.workspaceName !== this.workspaceName)) {
// When the clicked workspace changes and the new one errors then show the new error message
this.setState({
hasError: true,
workspaceName: this.workspaceName,
currentStep: LoadIdeSteps.START_WORKSPACE,
workspaceId: workspace.id,
});
this.showErrorAlert(workspace);
}
} else if (prevState.workspaceName !== this.workspaceName) {
// There is no error in the newly opened workspace so just reset the status back to the initial state
this.setState({ hasError: false, workspaceName: this.workspaceName, currentStep: LoadIdeSteps.INITIALIZING, workspaceId: workspace.id });
this.setState({
hasError: false,
workspaceName: this.workspaceName,
currentStep: LoadIdeSteps.INITIALIZING,
workspaceId: workspace.id,
});
}
this.debounce.setDelay(1000);
}
Expand Down Expand Up @@ -198,7 +225,7 @@ class IdeLoaderContainer extends React.PureComponent<Props, State> {
private async verboseModeHandler(workspace: che.Workspace) {
try {
await this.props.startWorkspace(workspace.id, { 'debug-workspace-start': true });
await this.props.deleteWorkspaceLogs(workspace.id);
this.props.deleteWorkspaceLogs(workspace.id);
this.setState({
currentStep: LoadIdeSteps.INITIALIZING,
hasError: false
Expand All @@ -223,7 +250,7 @@ class IdeLoaderContainer extends React.PureComponent<Props, State> {
}
}

private updateIdeUrl(runtime: api.che.workspace.Runtime): void {
private async updateIdeUrl(runtime: api.che.workspace.Runtime): Promise<void> {
let ideUrl = '';
const machines = runtime.machines || {};
for (const machineName of Object.keys(machines)) {
Expand All @@ -240,6 +267,16 @@ class IdeLoaderContainer extends React.PureComponent<Props, State> {
this.showAlert('Don\'t know what to open, IDE url is not defined.');
return;
}
if (this.props.isDevelopment) {
// workaround to open IDE in iframe while serving dashboard locally
try {
const windowRef = window.open(ideUrl);
await delay(2000);
windowRef?.close();
} catch (e) {
// noop
}
}
this.setState({ currentStep: LoadIdeSteps.OPEN_IDE, ideUrl });
}

Expand All @@ -254,7 +291,7 @@ class IdeLoaderContainer extends React.PureComponent<Props, State> {
const workspace = this.props.allWorkspaces.find(workspace =>
workspace.id === workspaceId);
if (workspace && workspace.runtime) {
this.updateIdeUrl(workspace.runtime);
await this.updateIdeUrl(workspace.runtime);
}
}

Expand Down Expand Up @@ -308,7 +345,7 @@ class IdeLoaderContainer extends React.PureComponent<Props, State> {
workspaceId={workspaceId || ''}
preselectedTabKey={preselectedTabKey}
ideUrl={ideUrl}
hasError={hasError === true}
hasError={hasError}
workspaceName={workspaceName || ''}
callbacks={this.loadFactoryPageCallbacks}
/>
Expand All @@ -320,12 +357,13 @@ class IdeLoaderContainer extends React.PureComponent<Props, State> {
const mapStateToProps = (state: AppState) => ({
workspace: selectWorkspaceById(state),
allWorkspaces: selectAllWorkspaces(state),
workspacesLogs: selectLogs(state)
workspacesLogs: selectLogs(state),
isDevelopment: selectIsDevelopment(state),
});

const connector = connect(
mapStateToProps,
WorkspaceStore.actionCreators,
);
type MappedProps = ConnectedProps<typeof connector> | any;
type MappedProps = ConnectedProps<typeof connector>;
export default connector(IdeLoaderContainer);
80 changes: 37 additions & 43 deletions src/containers/__tests__/IdeLoader.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/

import React from 'react';
import { Action } from 'redux';
import { Provider } from 'react-redux';
import { AlertActionLink } from '@patternfly/react-core';
import { RenderResult, render, screen } from '@testing-library/react';
Expand All @@ -21,13 +22,24 @@ import { createFakeWorkspace } from '../../store/__mocks__/workspace';
import { WorkspaceStatus } from '../../services/helpers/types';
import IdeLoaderContainer, { LoadIdeSteps } from '../IdeLoader';
import { AlertOptions } from '../../pages/IdeLoader';
import { AppThunk } from '../../store';
import { ActionCreators } from '../../store/Workspaces';

const showAlertMock = jest.fn();
const requestWorkspaceMock = jest.fn().mockResolvedValue(undefined);
const startWorkspaceMock = jest.fn().mockResolvedValue(undefined);

jest.mock('../../store/Workspaces/index', () => {
return { actionCreators: {} };
return {
actionCreators: {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
requestWorkspace: (id: string): AppThunk<Action, Promise<void>> => async (): Promise<void> => { requestWorkspaceMock(); },
// eslint-disable-next-line @typescript-eslint/no-unused-vars
startWorkspace: (id: string): AppThunk<Action, Promise<void>> => async (): Promise<void> => { startWorkspaceMock(); }
,
} as ActionCreators,
};
});

let showAlert = jest.fn();

jest.mock('../../pages/IdeLoader', () => {
return function DummyWizard(props: {
hasError: boolean,
Expand All @@ -40,7 +52,7 @@ jest.mock('../../pages/IdeLoader', () => {
}
}): React.ReactElement {
if (props.callbacks) {
props.callbacks.showAlert = showAlert;
props.callbacks.showAlert = showAlertMock;
}
return (<div>Dummy Wizard
<div data-testid="ide-loader-has-error">{props.hasError.toString()}</div>
Expand Down Expand Up @@ -100,41 +112,35 @@ describe('IDE Loader container', () => {
const renderComponent = (
namespace: string,
workspaceName: string,
startWorkspace: jest.Mock,
requestWorkspace: jest.Mock,
): RenderResult => {
const { history, location, match } = getMockRouterProps(ROUTE.IDE_LOADER, { namespace, workspaceName });
return render(
<Provider store={store}>
<IdeLoaderContainer match={match}
<IdeLoaderContainer
match={match}
history={history}
location={location}
requestWorkspace={async (id: string) => requestWorkspace(id)}
startWorkspace={async (id: string) => startWorkspace(id)} />
/>
</Provider>,
);
};

beforeEach(() => {
showAlert = jest.fn();
afterEach(() => {
jest.resetAllMocks();
});

it('should show an error if something wrong', () => {
const namespace = 'admin3';
const workspaceName = 'name-wksp-4';

const requestWorkspace = jest.fn();
const startWorkspace = jest.fn();

renderComponent(
namespace,
workspaceName,
startWorkspace,
requestWorkspace);
);

expect(startWorkspace).not.toBeCalled();
expect(requestWorkspace).not.toBeCalled();
expect(showAlert).toBeCalledWith(expect.objectContaining({
expect(startWorkspaceMock).not.toBeCalled();
expect(requestWorkspaceMock).not.toBeCalled();
expect(showAlertMock).toBeCalledWith(expect.objectContaining({
alertVariant: 'danger',
title: 'Failed to find the target workspace.'
}));
Expand All @@ -150,22 +156,18 @@ describe('IDE Loader container', () => {
const namespace = 'admin3';
const workspaceName = 'name-wksp-3';

const requestWorkspace = jest.fn();
const startWorkspace = jest.fn();

renderComponent(
namespace,
workspaceName,
startWorkspace,
requestWorkspace);
);

expect(startWorkspace).not.toBeCalled();
expect(requestWorkspace).not.toBeCalled();
expect(startWorkspaceMock).not.toBeCalled();
expect(requestWorkspaceMock).not.toBeCalled();

expect(showAlert).toBeCalledTimes(1);
expect(showAlertMock).toBeCalledTimes(1);

const errorAlerts = <React.Fragment><AlertActionLink onClick={() => jest.fn()}>Open in Verbose mode</AlertActionLink><AlertActionLink onClick={() => jest.fn()}>Open Logs</AlertActionLink></React.Fragment>;
const firstCalledArgs = showAlert.mock.calls[0][0];
const firstCalledArgs = showAlertMock.mock.calls[0][0];
expect(firstCalledArgs.title).toEqual('Workspace name-wksp-3 failed to start');
expect(firstCalledArgs.alertVariant).toEqual('danger');
expect(JSON.stringify(firstCalledArgs.alertActionLinks)).toEqual(JSON.stringify(errorAlerts));
Expand All @@ -182,17 +184,13 @@ describe('IDE Loader container', () => {
const workspaceId = 'id-wksp-1';
const workspaceName = 'name-wksp-1';

const requestWorkspace = jest.fn();
const startWorkspace = jest.fn();

renderComponent(
namespace,
workspaceName,
startWorkspace,
requestWorkspace);
);

expect(startWorkspace).toHaveBeenCalledTimes(1);
expect(requestWorkspace).not.toBeCalled();
expect(startWorkspaceMock).toHaveBeenCalledTimes(1);
expect(requestWorkspaceMock).not.toBeCalled();

const elementHasError = screen.getByTestId('ide-loader-has-error');
expect(elementHasError.innerHTML).toEqual('false');
Expand All @@ -215,17 +213,13 @@ describe('IDE Loader container', () => {
const namespace = 'admin2';
const workspaceName = 'name-wksp-2';

const requestWorkspace = jest.fn();
const startWorkspace = jest.fn();

renderComponent(
namespace,
workspaceName,
startWorkspace,
requestWorkspace);
);

expect(startWorkspace).not.toBeCalled();
expect(requestWorkspace).not.toBeCalled();
expect(startWorkspaceMock).not.toBeCalled();
expect(requestWorkspaceMock).not.toBeCalled();

const elementHasError = screen.getByTestId('ide-loader-has-error');
expect(elementHasError.innerHTML).toEqual('false');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ function createFakeStore(metadata?: che.DevfileMetaData[]): Store {
},
user: {} as any,
infrastructureNamespace: {} as any,
environment: {} as any,
userPreferences: {} as any,
};
const middleware = [thunk];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ function createFakeStore(metadata?: che.DevfileMetaData[]): Store {
},
user: {} as any,
infrastructureNamespace: {} as any,
environment: {} as any,
userPreferences: {} as any,
};
const middleware = [thunk];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ function createFakeStore(metadata?: che.DevfileMetaData[]): Store {
},
user: {} as any,
infrastructureNamespace: {} as any,
environment: {} as any,
userPreferences: {} as any,
};
const middleware = [thunk];
Expand Down
1 change: 1 addition & 0 deletions src/pages/GetStarted/__tests__/GetStarted.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ function createFakeStore(): Store {
devfileRegistries: {} as any,
user: {} as any,
infrastructureNamespace: {} as any,
environment: {} as any,
userPreferences: {} as any,
};
const middleware = [thunk];
Expand Down
Loading