Skip to content

Commit

Permalink
chore: more tests
Browse files Browse the repository at this point in the history
Signed-off-by: Carina Ursu <[email protected]>
  • Loading branch information
ursucarina committed Apr 14, 2023
1 parent 294d8a7 commit 546b3b6
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const ExecutionTab: React.FC<ExecutionTabProps> = ({ tabType }) => {
<DetailsPanelContextProvider>
<div className={styles.nodesContainer}>
{tabType === tabs.nodes.id && (
<NodeExecutionsTable filterState={filterState}/>
<NodeExecutionsTable filterState={filterState} />
)}
{tabType === tabs.graph.id && <WorkflowGraph />}
{tabType === tabs.timeline.id && <ExecutionTimelineContainer />}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import * as React from 'react';
import { fireEvent, render, waitFor, screen } from '@testing-library/react';
import { filterLabels } from 'components/Executions/filters/constants';
import { nodeExecutionStatusFilters } from 'components/Executions/filters/statusFilters';
import { oneFailedTaskWorkflow } from 'mocks/data/fixtures/oneFailedTaskWorkflow';
import { insertFixture } from 'mocks/data/insertFixture';
import { mockServer } from 'mocks/server';
import { Execution } from 'models/Execution/types';
import * as React from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { createTestQueryClient } from 'test/utils';
import { ExecutionContext } from 'components/Executions/contexts';
import { tabs } from '../constants';
import { listNodeExecutions, listTaskExecutions } from 'models/Execution/api';
import { NodeExecutionPhase } from 'models';
import { mockWorkflowId } from 'mocks/data/fixtures/types';
import { NodeExecutionDetailsContext } from 'components/Executions/contextProvider/NodeExecutionDetails';
import { transformerWorkflowToDag } from 'components/WorkflowGraph/transformerWorkflowToDag';
import { ExecutionNodeViews } from '../ExecutionNodeViews';
import { tabs } from '../constants';

jest.mock('components/Executions/Tables/NodeExecutionRow', () => ({
NodeExecutionRow: jest.fn(({ nodeExecution }) => (
NodeExecutionRow: jest.fn(({ node }) => (
<div data-testid="node-execution-row">
<span id="node-execution-col-id">{nodeExecution?.id?.nodeId}</span>
<span id="node-execution-col-id">{node?.execution?.id?.nodeId}</span>
</div>
)),
}));
Expand All @@ -40,6 +45,14 @@ jest.mock(
NodeExecutionName: jest.fn(({ name }) => <div>{name}</div>),
}),
);
jest.mock('models/Execution/api', () => ({
listNodeExecutions: jest.fn(),
listTaskExecutions: jest.fn(),
}));

jest.mock('components/WorkflowGraph/transformerWorkflowToDag', () => ({
transformerWorkflowToDag: jest.fn(),
}));

// ExecutionNodeViews uses query params for NE list, so we must match them
// for the list to be returned properly
Expand All @@ -53,34 +66,103 @@ describe('ExecutionNodeViews', () => {
let queryClient: QueryClient;
let execution: Execution;
let fixture: ReturnType<typeof oneFailedTaskWorkflow.generate>;

beforeEach(() => {
fixture = oneFailedTaskWorkflow.generate();
execution = fixture.workflowExecutions.top.data;
insertFixture(mockServer, fixture);
const nodeExecutions = fixture.workflowExecutions.top.nodeExecutions;

mockServer.insertNodeExecutionList(
execution.id,
Object.values(nodeExecutions).map(({ data }) => data),
baseQueryParams,
);
mockServer.insertNodeExecutionList(
execution.id,
[nodeExecutions.failedNode.data],
{
...baseQueryParams,
filters: 'value_in(phase,FAILED)',
},
const nodeExecutionsArray = Object.values(nodeExecutions).map(
({ data }) => data,
);
transformerWorkflowToDag.mockImplementation(_ => {
return {
dag: {
id: 'start-node',
scopedId: 'start-node',
value: {
id: 'start-node',
},
type: 4,
name: 'start',
nodes: [
{
id: 'start-node',
scopedId: 'start-node',
value: {
inputs: [],
upstreamNodeIds: [],
outputAliases: [],
id: 'start-node',
},
type: 4,
name: 'start',
nodes: [],
edges: [],
},
{
id: 'end-node',
scopedId: 'end-node',
value: {
inputs: [],
upstreamNodeIds: [],
outputAliases: [],
id: 'end-node',
},
type: 5,
name: 'end',
nodes: [],
edges: [],
},
...nodeExecutionsArray.map(n => ({
id: n.id.nodeId,
scopedId: n.scopedId,
execution: n,
// type: dTypes.gateNode,
name: n.id.nodeId,
type: 3,
nodes: [],
edges: [],
})),
],
},
staticExecutionIdsMap: {},
};
});
listNodeExecutions.mockImplementation((_, filters) => {
let finalNodes = nodeExecutionsArray;
if (filters?.filter?.length) {
const phases = filters?.filter
?.filter(f => f.key === 'phase')?.[0]
.value?.map(f => NodeExecutionPhase[f]);
finalNodes = finalNodes.filter(n => {
return phases.includes(n.closure.phase);
});
}
return Promise.resolve({
entities: Object.values(finalNodes),
});
});
listTaskExecutions.mockImplementation(() => {
return Promise.resolve({
entities: [],
});
});
queryClient = createTestQueryClient();
});

const renderViews = () =>
render(
<QueryClientProvider client={queryClient}>
<ExecutionContext.Provider value={{ execution }}>
<ExecutionNodeViews />
<NodeExecutionDetailsContext.Provider
value={{
compiledWorkflowClosure: {} as any,
getNodeExecutionDetails: jest.fn.call,
workflowId: mockWorkflowId,
}}
>
<ExecutionNodeViews />
</NodeExecutionDetailsContext.Provider>
</ExecutionContext.Provider>
</QueryClientProvider>,
);
Expand All @@ -90,7 +172,7 @@ describe('ExecutionNodeViews', () => {
const failedNodeName = nodeExecutions.failedNode.data.id.nodeId;
const succeededNodeName = nodeExecutions.pythonNode.data.id.nodeId;

const { getByText, queryByText, getByLabelText } = renderViews();
const { getByText, queryByText, queryAllByTestId } = renderViews();

await waitFor(() => getByText(tabs.nodes.label));

Expand All @@ -99,29 +181,41 @@ describe('ExecutionNodeViews', () => {

// Ensure we are on Nodes tab
await fireEvent.click(nodesTab);
await waitFor(() => {
const nodes = queryAllByTestId('node-execution-row');
return nodes?.length === 2;
});

await waitFor(() => queryByText(succeededNodeName));

const statusButton = await waitFor(() => getByText(filterLabels.status));

// Apply 'Failed' filter and wait for list to include only the failed item
await fireEvent.click(statusButton);

const failedFilter = await waitFor(() =>
getByLabelText(nodeExecutionStatusFilters.failed.label),
screen.getByLabelText(nodeExecutionStatusFilters.failed.label),
);

// Wait for succeeded task to disappear and ensure failed task remains
await fireEvent.click(failedFilter);
await waitFor(() => queryByText(failedNodeName));
await waitFor(() => {
const nodes = queryAllByTestId('node-execution-row');
return nodes?.length === 1;
});

expect(queryByText(succeededNodeName)).not.toBeInTheDocument();

expect(queryByText(failedNodeName)).toBeInTheDocument();

// Switch to the Graph tab
await fireEvent.click(statusButton);
await fireEvent.click(timelineTab);
await waitFor(() => queryByText(succeededNodeName));

// expect all initital nodes to be rendered
expect(queryByText(succeededNodeName)).toBeInTheDocument();
expect(queryByText(failedNodeName)).toBeInTheDocument();

// Switch back to Nodes Tab and verify filter still applied
await fireEvent.click(nodesTab);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import { MemoryRouter } from 'react-router';
import { createTestQueryClient } from 'test/utils';
import { NodeExecutionDetailsPanelContent } from '../NodeExecutionDetailsPanelContent';

jest.mock('components/Executions/ExecutionDetails/ExecutionDetailsActions', () => ({
ExecutionDetailsActions: jest.fn(() => (
<div data-test-id="execution-details-actions"></div>
))
}));
jest.mock(
'components/Executions/ExecutionDetails/ExecutionDetailsActions',
() => ({
ExecutionDetailsActions: jest.fn(() => (
<div data-test-id="execution-details-actions"></div>
)),
}),
);
jest.mock('components/Workflow/workflowQueries');
const { fetchWorkflow } = require('components/Workflow/workflowQueries');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,14 @@ describe('ExecutionDetails > Timeline > TaskNames', () => {
<WorkflowNodeExecutionsContext.Provider
value={{
nodeExecutionsById,
dagData: {
dagError: null,
mergedDag: {},
},
initialDNodes: props.nodes,
setCurrentNodeExecutionsById: () => {},
setShouldUpdate: () => {},
shouldUpdate: false,
}}
>
<TaskNames {...props} />
Expand Down
Loading

0 comments on commit 546b3b6

Please sign in to comment.