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

feat: Allow to archive workflow from flyteconsole #361

Merged
merged 13 commits into from
Apr 11, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,7 @@ export function getActionsCell(
</IconButton>
)}
{!!onArchiveClick && (
<IconButton
size="small"
title={t('archiveActionString', isArchived)}
onClick={onArchiveClick}
>
<IconButton size="small" title={t('archiveAction', isArchived)} onClick={onArchiveClick}>
{getArchiveIcon(isArchived)}
</IconButton>
)}
Expand Down
30 changes: 15 additions & 15 deletions src/components/Project/ProjectWorkflows.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { WaitForData } from 'components/common/WaitForData';
import { useWorkflowShowArchivedState } from 'components/Workflow/filters/useWorkflowShowArchivedState';
import { SearchableWorkflowNameList } from 'components/Workflow/SearchableWorkflowNameList';
import { Admin } from 'flyteidl';
import { limits } from 'models/AdminEntity/constants';
import { FilterOperationName, SortDirection } from 'models/AdminEntity/types';
import { SortDirection } from 'models/AdminEntity/types';
import { workflowSortFields } from 'models/Workflow/constants';
import * as React from 'react';
import { useWorkflowInfoList } from '../Workflow/useWorkflowInfoList';
Expand All @@ -12,33 +12,33 @@ export interface ProjectWorkflowsProps {
domainId: string;
}

const DEFAULT_SORT = {
direction: SortDirection.ASCENDING,
key: workflowSortFields.name,
};

/** A listing of the Workflows registered for a project */
export const ProjectWorkflows: React.FC<ProjectWorkflowsProps> = ({
domainId: domain,
projectId: project,
}) => {
const archivedFilter = useWorkflowShowArchivedState();
const workflows = useWorkflowInfoList(
{ domain, project },
{
limit: limits.NONE,
sort: {
direction: SortDirection.ASCENDING,
key: workflowSortFields.name,
},
// Hide archived workflows from the list
filter: [
{
key: 'state',
operation: FilterOperationName.EQ,
value: Admin.NamedEntityState.NAMED_ENTITY_ACTIVE,
},
],
sort: DEFAULT_SORT,
filter: [archivedFilter.getFilter()],
},
);

return (
<WaitForData {...workflows}>
<SearchableWorkflowNameList workflows={workflows.value} />
<SearchableWorkflowNameList
workflows={workflows.value}
showArchived={archivedFilter.showArchived}
onArchiveFilterChange={archivedFilter.setShowArchived}
/>
</WaitForData>
);
};
61 changes: 51 additions & 10 deletions src/components/Project/test/ProjectWorkflows.test.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
import { render, waitFor } from '@testing-library/react';
import { fireEvent, render, waitFor } from '@testing-library/react';
import { APIContext } from 'components/data/apiContext';
import { mockAPIContextValue } from 'components/data/__mocks__/apiContext';
import { Admin } from 'flyteidl';
import { FilterOperationName } from 'models/AdminEntity/types';
import { listNamedEntities } from 'models/Common/api';
import { NamedEntity } from 'models/Common/types';
import { getUserProfile, listNamedEntities } from 'models/Common/api';
import { NamedEntity, UserProfile } from 'models/Common/types';
import * as React from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { MemoryRouter } from 'react-router';
import { createWorkflowName } from 'test/modelUtils';
import { createTestQueryClient } from 'test/utils';
import { ProjectWorkflows } from '../ProjectWorkflows';

const sampleUserProfile: UserProfile = {
subject: 'subject',
} as UserProfile;

jest.mock('notistack', () => ({
useSnackbar: () => ({ enqueueSnackbar: jest.fn() }),
}));

describe('ProjectWorkflows', () => {
const project = 'TestProject';
const domain = 'TestDomain';
let workflowNames: NamedEntity[];
let queryClient: QueryClient;
let mockListNamedEntities: jest.Mock<ReturnType<typeof listNamedEntities>>;
let mockGetUserProfile: jest.Mock<ReturnType<typeof getUserProfile>>;

beforeEach(() => {
mockGetUserProfile = jest.fn().mockResolvedValue(null);
queryClient = createTestQueryClient();
workflowNames = ['MyWorkflow', 'MyOtherWorkflow'].map((name) =>
createWorkflowName({ domain, name, project }),
);
Expand All @@ -25,13 +39,16 @@ describe('ProjectWorkflows', () => {

const renderComponent = () =>
render(
<APIContext.Provider
value={mockAPIContextValue({
listNamedEntities: mockListNamedEntities,
})}
>
<ProjectWorkflows projectId={project} domainId={domain} />
</APIContext.Provider>,
<QueryClientProvider client={queryClient}>
<APIContext.Provider
value={mockAPIContextValue({
listNamedEntities: mockListNamedEntities,
getUserProfile: mockGetUserProfile,
})}
>
<ProjectWorkflows projectId={project} domainId={domain} />
</APIContext.Provider>
</QueryClientProvider>,
{ wrapper: MemoryRouter },
);

Expand All @@ -52,4 +69,28 @@ describe('ProjectWorkflows', () => {
}),
);
});

it('should display checkbox if user login', async () => {
mockGetUserProfile.mockResolvedValue(sampleUserProfile);
const { getAllByRole } = renderComponent();
await waitFor(() => {});
const checkboxes = getAllByRole(/checkbox/i) as HTMLInputElement[];
expect(checkboxes).toHaveLength(1);
expect(checkboxes[0]).toBeTruthy();
expect(checkboxes[0]?.checked).toEqual(false);
});

/** user doesn't have its own workflow */
it('clicking show archived should hide active workflows', async () => {
mockGetUserProfile.mockResolvedValue(sampleUserProfile);
const { getByText, queryByText, getAllByRole } = renderComponent();
await waitFor(() => {});
const checkboxes = getAllByRole(/checkbox/i) as HTMLInputElement[];
expect(checkboxes[0]).toBeTruthy();
expect(checkboxes[0]?.checked).toEqual(false);
await waitFor(() => expect(getByText('MyWorkflow')));
fireEvent.click(checkboxes[0]);
// when user selects checkbox, table should have no workflows to display
await waitFor(() => expect(queryByText('MyWorkflow')).toBeNull());
anrusina marked this conversation as resolved.
Show resolved Hide resolved
});
});
Loading