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: workspace actions #1233

Merged
merged 1 commit into from
Oct 22, 2024
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 @@ -42,9 +42,6 @@ export class RecentItemWorkspaceActions extends React.PureComponent<Props> {
context={context}
isPlain
menuAppendTo={menuAppendTo}
onAction={async () => {
// no-op
}}
position="right"
toggle="kebab-toggle"
workspace={item.workspace}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,14 @@ export class WorkspaceActionsDropdown extends React.PureComponent<Props, State>
};
}

private get hasKebabToggle(): boolean {
return this.props.toggle === 'kebab-toggle';
}

private buildToggle(): React.ReactElement {
const { isDisabled = false, toggle, workspace } = this.props;
const { isDisabled = false, workspace } = this.props;

if (toggle === 'kebab-toggle') {
if (this.hasKebabToggle) {
return (
<KebabToggle
aria-label="Actions"
Expand Down Expand Up @@ -157,14 +161,21 @@ export class WorkspaceActionsDropdown extends React.PureComponent<Props, State>
);
};

return [
const items = [
getItem(WorkspaceAction.OPEN_IDE, isTerminating),
getItem(WorkspaceAction.START_DEBUG_AND_OPEN_LOGS, isTerminating || isStopped === false),
getItem(WorkspaceAction.START_IN_BACKGROUND, isTerminating || isStopped === false),
getItem(WorkspaceAction.START_DEBUG_AND_OPEN_LOGS, isTerminating || !isStopped),
getItem(WorkspaceAction.START_IN_BACKGROUND, isTerminating || !isStopped),
getItem(WorkspaceAction.RESTART_WORKSPACE, isTerminating || isStopped),
getItem(WorkspaceAction.STOP_WORKSPACE, isTerminating || isStopped),
getItem(WorkspaceAction.DELETE_WORKSPACE, isTerminating),
];

// The 'Workspace Details' action is available only with kebab-toggle because this actions widget is used on the workspace details page without kebab-toggle
if (this.hasKebabToggle) {
items.push(getItem(WorkspaceAction.WORKSPACE_DETAILS, false));
}

return items;
}

render(): React.ReactElement {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import { Location } from 'react-router-dom';

import { WorkspaceActionsDeleteConfirmation } from '@/contexts/WorkspaceActions/DeleteConfirmation';
import { lazyInject } from '@/inversify.config';
import { buildIdeLoaderLocation, toHref } from '@/services/helpers/location';
import {
buildIdeLoaderLocation,
buildWorkspaceDetailsLocation,
toHref,
} from '@/services/helpers/location';
import { LoaderTab, WorkspaceAction } from '@/services/helpers/types';
import { TabManager } from '@/services/tabManager';
import { Workspace } from '@/services/workspace-adapter';
Expand Down Expand Up @@ -67,6 +71,14 @@ class WorkspaceActionsProvider extends React.Component<Props, State> {
this.tabManager.open(link);
}

/**
* replace the current tab with the given location
*/
private replaceLocation(location: Location): void {
const link = toHref(location);
this.tabManager.replace(link);
}

private async deleteWorkspace(workspace: Workspace): Promise<void> {
if (this.deleting.has(workspace.uid)) {
console.warn(`Workspace "${workspace.name}" is being deleted.`);
Expand Down Expand Up @@ -114,6 +126,10 @@ class WorkspaceActionsProvider extends React.Component<Props, State> {
this.handleLocation(buildIdeLoaderLocation(workspace));
break;
}
case WorkspaceAction.WORKSPACE_DETAILS: {
this.replaceLocation(buildWorkspaceDetailsLocation(workspace));
break;
}
case WorkspaceAction.START_DEBUG_AND_OPEN_LOGS: {
await this.props.startWorkspace(workspace, {
'debug-workspace-start': true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ import {
WorkspaceActionsConsumer,
} from '@/contexts/WorkspaceActions';
import WorkspaceActionsProvider from '@/contexts/WorkspaceActions/Provider';
import { container } from '@/inversify.config';
import getComponentRenderer, { screen } from '@/services/__mocks__/getComponentRenderer';
import { WorkspaceAction } from '@/services/helpers/types';
import { TabManager } from '@/services/tabManager';
import { AppThunk } from '@/store';
import { DevWorkspaceBuilder } from '@/store/__mocks__/devWorkspaceBuilder';
import { FakeStoreBuilder } from '@/store/__mocks__/storeBuilder';
Expand Down Expand Up @@ -67,6 +69,10 @@ const wantDelete = ['1234', '5678'] as WantDelete;

const mockHandleAction: jest.Mock = jest.fn();

const mockWindowReplace = jest.fn();

const mockTabManagerOpen = jest.fn();

describe('WorkspaceActionsProvider', () => {
let store: Store;
let user: UserEvent;
Expand All @@ -92,6 +98,18 @@ describe('WorkspaceActionsProvider', () => {
jest.useFakeTimers();

user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });

class MockTabManager extends TabManager {
public open(url: string): void {
mockTabManagerOpen(url);
}
public replace(url: string): void {
mockWindowReplace(url);
}
}

container.snapshot();
container.rebind(TabManager).to(MockTabManager).inSingletonScope();
});

afterEach(() => {
Expand Down Expand Up @@ -138,8 +156,6 @@ describe('WorkspaceActionsProvider', () => {
});

describe('handle actions', () => {
window.open = jest.fn();

describe('delete workspace', () => {
test('succeeded (with debouncing)', async () => {
console.warn = jest.fn();
Expand Down Expand Up @@ -209,10 +225,24 @@ describe('WorkspaceActionsProvider', () => {
// make sure all timers are executed
await jest.advanceTimersByTimeAsync(1000);

expect(window.open).toHaveBeenCalledTimes(1);
expect(window.open).toHaveBeenCalledWith(
expect.stringContaining('/ide/user-che/wksp-1234'),
expect.stringContaining('/ide/user-che/wksp-1234'),
expect(mockTabManagerOpen).toHaveBeenCalledTimes(1);
expect(mockTabManagerOpen).toHaveBeenCalledWith('http://localhost/#/ide/user-che/wksp-1234');
});

test('open workspace details', async () => {
renderComponent(store, WorkspaceAction.WORKSPACE_DETAILS, '1234');

// get and click start button
const handleActionBtn = screen.getByTestId('test-component-handle-action');

await user.click(handleActionBtn);

// make sure all timers are executed
await jest.advanceTimersByTimeAsync(1000);

expect(mockWindowReplace).toHaveBeenCalledTimes(1);
expect(mockWindowReplace).toHaveBeenCalledWith(
'http://localhost/#/workspace/user-che/wksp-1234',
);
});

Expand All @@ -235,9 +265,8 @@ describe('WorkspaceActionsProvider', () => {
{ 'debug-workspace-start': true },
);

expect(window.open).toHaveBeenCalledWith(
expect.stringContaining('/ide/user-che/wksp-5678?tab=Logs'),
expect.stringContaining('/ide/user-che/wksp-5678?tab=Logs'),
expect(mockTabManagerOpen).toHaveBeenCalledWith(
'http://localhost/#/ide/user-che/wksp-5678?tab=Logs',
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

import { Location } from 'react-router-dom';

import { toHref } from '@/services/helpers/location';
import { buildWorkspaceDetailsLocation, toHref } from '@/services/helpers/location';
import { constructWorkspace } from '@/services/workspace-adapter';
import { DevWorkspaceBuilder } from '@/store/__mocks__/devWorkspaceBuilder';

describe('location', () => {
test('toHref', () => {
Expand All @@ -25,4 +27,12 @@ describe('location', () => {
};
expect(toHref(location)).toEqual(`${window.location.origin}/#/foo?bar=baz`);
});

test('buildWorkspaceDetailsLocation', () => {
const devWorkspaceBuilder = new DevWorkspaceBuilder()
.withName('wksp')
.withNamespace('che-user');
const workspace = constructWorkspace(devWorkspaceBuilder.build());
expect(buildWorkspaceDetailsLocation(workspace).pathname).toEqual(`/workspace/che-user/wksp`);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ export function buildWorkspacesLocation(): Location {
return _buildLocationObject(ROUTE.WORKSPACES);
}

export function buildWorkspaceDetailsLocation(workspace: Workspace): Location {
const path = ROUTE.WORKSPACE_DETAILS.replace(':namespace', workspace.namespace).replace(
':workspaceName',
workspace.name,
);
return _buildLocationObject(path);
}

export function buildUserPreferencesLocation(tab?: UserPreferencesTab): Location {
let pathAndQuery: string;
if (!tab) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export enum WorkspaceAction {
START_DEBUG_AND_OPEN_LOGS = 'Open in Debug mode',
START_IN_BACKGROUND = 'Start in background',
STOP_WORKSPACE = 'Stop Workspace',
WORKSPACE_DETAILS = 'Workspace Details',
}

export enum UserPreferencesTab {
Expand Down
Loading