[arvados] created: 2.7.0-5820-ge136acc689
git repository hosting
git at public.arvados.org
Fri Jan 12 20:22:21 UTC 2024
at e136acc6897312f1b82e47fe038aba806855988c (commit)
commit e136acc6897312f1b82e47fe038aba806855988c
Author: Stephen Smith <stephen at curii.com>
Date: Fri Jan 12 15:20:58 2024 -0500
21366: Add unit tests to verify io panel doesn't get stuck showing spinner
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>
diff --git a/services/workbench2/src/views/process-panel/process-io-card.test.tsx b/services/workbench2/src/views/process-panel/process-io-card.test.tsx
new file mode 100644
index 0000000000..a1ee7d61fa
--- /dev/null
+++ b/services/workbench2/src/views/process-panel/process-io-card.test.tsx
@@ -0,0 +1,216 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import React from 'react';
+import { mount, configure } from 'enzyme';
+import { combineReducers, createStore } from "redux";
+import { CircularProgress, MuiThemeProvider, Tab, TableBody, TableCell } from "@material-ui/core";
+import { CustomTheme } from 'common/custom-theme';
+import Adapter from "enzyme-adapter-react-16";
+import { Provider } from 'react-redux';
+import configureMockStore from 'redux-mock-store'
+import { ProcessIOCard, ProcessIOCardType } from './process-io-card';
+import { DefaultView } from "components/default-view/default-view";
+import { DefaultCodeSnippet } from "components/default-code-snippet/default-code-snippet";
+import { ProcessOutputCollectionFiles } from './process-output-collection-files';
+import { MemoryRouter } from 'react-router-dom';
+
+
+const middlewares = [];
+const mockStore = configureMockStore(middlewares);
+jest.mock('views/process-panel/process-output-collection-files');
+configure({ adapter: new Adapter() });
+
+describe('renderers', () => {
+ let store;
+
+ describe('ProcessStatus', () => {
+
+ beforeEach(() => {
+ store = createStore(combineReducers({
+ auth: (state: any = {}, action: any) => state,
+ }));
+ });
+
+ it('shows main process input loading when raw or params null', () => {
+ // when
+ let panel = mount(
+ <Provider store={store}>
+ <MuiThemeProvider theme={CustomTheme}>
+ <ProcessIOCard
+ label={ProcessIOCardType.INPUT}
+ process={false} // Treat as a main process, no requestingContainerUuid
+ params={null}
+ raw={{}}
+ />
+ </MuiThemeProvider>
+ </Provider>
+ );
+
+ // then
+ expect(panel.find(Tab).exists()).toBeFalsy();
+ expect(panel.find(CircularProgress));
+
+ // when
+ panel = mount(
+ <Provider store={store}>
+ <MuiThemeProvider theme={CustomTheme}>
+ <ProcessIOCard
+ label={ProcessIOCardType.INPUT}
+ process={false} // Treat as a main process, no requestingContainerUuid
+ params={[]}
+ raw={null}
+ />
+ </MuiThemeProvider>
+ </Provider>
+ );
+
+ // then
+ expect(panel.find(Tab).exists()).toBeFalsy();
+ expect(panel.find(CircularProgress));
+ });
+
+ it('shows main process empty params and raw', () => {
+ // when
+ let panel = mount(
+ <Provider store={store}>
+ <MuiThemeProvider theme={CustomTheme}>
+ <ProcessIOCard
+ label={ProcessIOCardType.INPUT}
+ process={false} // Treat as a main process, no requestingContainerUuid
+ params={[]}
+ raw={{}}
+ />
+ </MuiThemeProvider>
+ </Provider>
+ );
+
+ // then
+ expect(panel.find(CircularProgress).exists()).toBeFalsy();
+ expect(panel.find(Tab).exists()).toBeFalsy();
+ expect(panel.find(DefaultView).text()).toEqual('No parameters found');
+ });
+
+ it('shows main process with raw', () => {
+ // when
+ const raw = {some: 'data'};
+ let panel = mount(
+ <Provider store={store}>
+ <MuiThemeProvider theme={CustomTheme}>
+ <ProcessIOCard
+ label={ProcessIOCardType.INPUT}
+ process={false} // Treat as a main process, no requestingContainerUuid
+ params={[]}
+ raw={raw}
+ />
+ </MuiThemeProvider>
+ </Provider>
+ );
+
+ // then
+ expect(panel.find(CircularProgress).exists()).toBeFalsy();
+ expect(panel.find(Tab).length).toBe(1);
+ expect(panel.find(DefaultCodeSnippet).text()).toContain(JSON.stringify(raw, null, 2));
+ });
+
+ it('shows main process with params', () => {
+ // when
+ const parameters = [{id: 'someId', label: 'someLabel', value: [{display: 'someValue'}]}];
+ let panel = mount(
+ <Provider store={store}>
+ <MuiThemeProvider theme={CustomTheme}>
+ <ProcessIOCard
+ label={ProcessIOCardType.INPUT}
+ process={false} // Treat as a main process, no requestingContainerUuid
+ params={parameters}
+ raw={{}}
+ />
+ </MuiThemeProvider>
+ </Provider>
+ );
+
+ // then
+ expect(panel.find(CircularProgress).exists()).toBeFalsy();
+ expect(panel.find(Tab).length).toBe(2); // Empty raw is shown if parameters are present
+ expect(panel.find(TableBody).text()).toContain('someId');
+ expect(panel.find(TableBody).text()).toContain('someLabel');
+ expect(panel.find(TableBody).text()).toContain('someValue');
+ });
+
+ // Subprocess
+
+ it('shows subprocess loading', () => {
+ // when
+ const subprocess = {containerRequest: {requestingContainerUuid: 'xyz'}};
+ let panel = mount(
+ <Provider store={store}>
+ <MuiThemeProvider theme={CustomTheme}>
+ <ProcessIOCard
+ label={ProcessIOCardType.INPUT}
+ process={subprocess} // Treat as a subprocess without outputUuid
+ params={null}
+ raw={null}
+ />
+ </MuiThemeProvider>
+ </Provider>
+ );
+
+ // then
+ expect(panel.find(Tab).exists()).toBeFalsy();
+ expect(panel.find(CircularProgress));
+ });
+
+ it('shows subprocess mounts', () => {
+ // when
+ const subprocess = {containerRequest: {requestingContainerUuid: 'xyz'}};
+ const sampleMount = {path: '/', pdh: 'abcdef12abcdef12abcdef12abcdef12+0'};
+ let panel = mount(
+ <Provider store={store}>
+ <MemoryRouter>
+ <MuiThemeProvider theme={CustomTheme}>
+ <ProcessIOCard
+ label={ProcessIOCardType.INPUT}
+ process={subprocess} // Treat as a subprocess without outputUuid
+ params={null}
+ raw={null}
+ mounts={[sampleMount]}
+ />
+ </MuiThemeProvider>
+ </MemoryRouter>
+ </Provider>
+ );
+
+ // then
+ expect(panel.find(CircularProgress).exists()).toBeFalsy();
+ expect(panel.find(Tab).length).toBe(1); // Empty raw is hidden in subprocesses
+ expect(panel.find(TableBody).text()).toContain(sampleMount.pdh);
+
+ });
+
+ it('shows subprocess output collection', () => {
+ // when
+ const subprocess = {containerRequest: {requestingContainerUuid: 'xyz'}};
+ const outputCollection = '123456789';
+ let panel = mount(
+ <Provider store={store}>
+ <MuiThemeProvider theme={CustomTheme}>
+ <ProcessIOCard
+ label={ProcessIOCardType.OUTPUT}
+ process={subprocess} // Treat as a subprocess with outputUuid
+ outputUuid={outputCollection}
+ params={null}
+ raw={null}
+ />
+ </MuiThemeProvider>
+ </Provider>
+ );
+
+ // then
+ expect(panel.find(CircularProgress).exists()).toBeFalsy();
+ expect(panel.find(Tab).length).toBe(1); // Empty raw is hidden in subprocesses
+ expect(panel.find(ProcessOutputCollectionFiles).prop('currentItemUuid')).toBe(outputCollection);
+ });
+
+ });
+});
commit 4af2e048f6efad08608670cb3ba4da144ec14301
Author: Stephen Smith <stephen at curii.com>
Date: Fri Jan 12 15:18:04 2024 -0500
21366: Tweaks the condition for displaying io panel subprocess spinner
It no longer shows when there are input mounts or output collection to show.
Also fixes possibility of spinner and no results showing simultaneously.
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>
diff --git a/services/workbench2/src/views/process-panel/process-io-card.tsx b/services/workbench2/src/views/process-panel/process-io-card.tsx
index b5afbf6545..393bde9667 100644
--- a/services/workbench2/src/views/process-panel/process-io-card.tsx
+++ b/services/workbench2/src/views/process-panel/process-io-card.tsx
@@ -219,7 +219,7 @@ export interface ProcessIOCardDataProps {
raw: any;
mounts?: InputCollectionMount[];
outputUuid?: string;
- showParams?: boolean;
+ forceShowParams?: boolean;
}
export interface ProcessIOCardActionProps {
@@ -251,7 +251,7 @@ export const ProcessIOCard = withStyles(styles)(
panelName,
process,
navigateTo,
- showParams,
+ forceShowParams,
}: ProcessIOCardProps) => {
const [mainProcTabState, setMainProcTabState] = useState(0);
const [subProcTabState, setSubProcTabState] = useState(0);
@@ -266,14 +266,18 @@ export const ProcessIOCard = withStyles(styles)(
const PanelIcon = label === ProcessIOCardType.INPUT ? InputIcon : OutputIcon;
const mainProcess = !(process && process!.containerRequest.requestingContainerUuid);
+ const showParamTable = mainProcess || forceShowParams;
const loading = raw === null || raw === undefined || params === null;
+
const hasRaw = !!(raw && Object.keys(raw).length > 0);
const hasParams = !!(params && params.length > 0);
// Subprocess
const hasInputMounts = !!(label === ProcessIOCardType.INPUT && mounts && mounts.length);
const hasOutputCollecton = !!(label === ProcessIOCardType.OUTPUT && outputUuid);
+ // Subprocess should not show loading if hasOutputCollection or hasInputMounts
+ const subProcessLoading = loading && !hasOutputCollecton && !hasInputMounts;
return (
<Card
@@ -350,7 +354,7 @@ export const ProcessIOCard = withStyles(styles)(
}
/>
<CardContent className={classes.content}>
- {mainProcess || showParams ? (
+ {showParamTable ? (
<>
{/* raw is undefined until params are loaded */}
{loading && (
@@ -377,14 +381,14 @@ export const ProcessIOCard = withStyles(styles)(
>
{/* params will be empty on processes without workflow definitions in mounts, so we only show raw */}
{hasParams && <Tab label="Parameters" />}
- {!showParams && <Tab label="JSON" />}
+ {!forceShowParams && <Tab label="JSON" />}
</Tabs>
{mainProcTabState === 0 && params && hasParams && (
<div className={classes.tableWrapper}>
<ProcessIOPreview
data={params}
showImagePreview={showImagePreview}
- valueLabel={showParams ? "Default value" : "Value"}
+ valueLabel={forceShowParams ? "Default value" : "Value"}
/>
</div>
)}
@@ -409,7 +413,7 @@ export const ProcessIOCard = withStyles(styles)(
) : (
// Subprocess
<>
- {loading && (
+ {subProcessLoading ? (
<Grid
container
item
@@ -418,8 +422,7 @@ export const ProcessIOCard = withStyles(styles)(
>
<CircularProgress />
</Grid>
- )}
- {!loading && (hasInputMounts || hasOutputCollecton || hasRaw) ? (
+ ) : !subProcessLoading && (hasInputMounts || hasOutputCollecton || hasRaw) ? (
<>
<Tabs
value={subProcTabState}
@@ -429,7 +432,7 @@ export const ProcessIOCard = withStyles(styles)(
>
{hasInputMounts && <Tab label="Collections" />}
{hasOutputCollecton && <Tab label="Collection" />}
- <Tab label="JSON" />
+ {hasRaw && <Tab label="JSON" />}
</Tabs>
<div className={classes.tableWrapper}>
{subProcTabState === 0 && hasInputMounts && <ProcessInputMounts mounts={mounts || []} />}
@@ -454,7 +457,7 @@ export const ProcessIOCard = withStyles(styles)(
/>
</>
)}
- {(subProcTabState === 1 || (!hasInputMounts && !hasOutputCollecton)) && (
+ {hasRaw && (subProcTabState === 1 || (!hasInputMounts && !hasOutputCollecton)) && (
<div className={classes.tableWrapper}>
<ProcessIORaw data={raw} />
</div>
diff --git a/services/workbench2/src/views/workflow-panel/registered-workflow-panel.tsx b/services/workbench2/src/views/workflow-panel/registered-workflow-panel.tsx
index 50192e543d..53c5928023 100644
--- a/services/workbench2/src/views/workflow-panel/registered-workflow-panel.tsx
+++ b/services/workbench2/src/views/workflow-panel/registered-workflow-panel.tsx
@@ -184,7 +184,7 @@ export const RegisteredWorkflowPanel = withStyles(styles)(connect(
label={ProcessIOCardType.INPUT}
params={inputParams}
raw={{}}
- showParams={true}
+ forceShowParams={true}
/>
</MPVPanelContent>
<MPVPanelContent forwardProps xs data-cy="process-outputs">
@@ -192,7 +192,7 @@ export const RegisteredWorkflowPanel = withStyles(styles)(connect(
label={ProcessIOCardType.OUTPUT}
params={outputParams}
raw={{}}
- showParams={true}
+ forceShowParams={true}
/>
</MPVPanelContent>
<MPVPanelContent xs>
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list