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

test: adds setup for mock-service-worker #127

Merged
merged 5 commits into from
Dec 4, 2020
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
"memoize-one": "^5.0.0",
"moment": "^2.18.1",
"moment-timezone": "^0.5.28",
"msw": "^0.24.1",
"object-hash": "^1.3.1",
"prettier": "1.19.1",
"protobufjs": "~6.8.0",
Expand Down
12 changes: 3 additions & 9 deletions src/common/env.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { Env } from 'config';
import { cloneDeep } from 'lodash';

/** Safely check for server environment */
export function isServer() {
try {
return __isServer;
} catch (e) {
return false;
}
}
const global = process != null ? process : window;

/** equivalent to process.env in server and client */
// tslint:disable-next-line:no-any
export const env: Env = (isServer() ? process.env : window.env) as any;
export const env: Env = cloneDeep(global.env) as any;
4 changes: 3 additions & 1 deletion src/common/test/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import {
timestampToDate
} from '../utils';

jest.mock('common/env');
jest.mock('common/env', () => ({
env: jest.requireActual('common/env').env
}));

import { Protobuf } from 'flyteidl';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ describe.skip('ExecutionNodeViews', () => {
props = { execution: workflowExecution };
});

it('is disabled', () => {});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these intentionally kept in?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. This keeps the test runner from throwing errors. I will remove them in the next PR when I fix and re-enable the commented-out tests.


const renderViews = () =>
render(
<QueryClientProvider client={queryClient}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ describe.skip('NodeExecutionsTable', () => {
return render(<Table {...await getProps()} />);
};

it('is disabled', () => {});

// it('renders task name for task nodes', async () => {
// const { queryAllByText, getAllByRole } = await renderTable();
// await waitFor(() => getAllByRole('listitem').length > 0);
Expand Down
6 changes: 6 additions & 0 deletions src/mocks/data/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Arbitrary start date used as a basis for generating timestamps
// to keep the mocked data consistent across runs
export const mockStartDate = new Date('2020-11-15T02:32:19.610Z');

// Workflow Execution duration in milliseconds
export const defaultWorkflowExecutionDuration = 1000 * 60 * 60 * 1.251;
15 changes: 15 additions & 0 deletions src/mocks/data/launchPlans.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Core } from 'flyteidl';
import { LaunchPlan } from 'models';

// TODO:
const basic: LaunchPlan = {
id: {
resourceType: Core.ResourceType.LAUNCH_PLAN,
project: 'flytetest',
domain: 'development',
name: 'Basic',
version: 'abc123'
}
} as LaunchPlan;

export const launchPlans = { basic };
Empty file.
8 changes: 8 additions & 0 deletions src/mocks/data/projects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export function emptyProject(id: string, name?: string) {
return {
id,
name: name ?? id,
domains: [],
description: ''
};
}
48 changes: 48 additions & 0 deletions src/mocks/data/workflowExecutions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { dateToTimestamp, millisecondsToDuration } from 'common/utils';
import { Admin } from 'flyteidl';
import { LiteralMap } from 'models/Common/types';
import { WorkflowExecutionPhase } from 'models/Execution/enums';
import { Execution, ExecutionMetadata } from 'models/Execution/types';
import { defaultWorkflowExecutionDuration, mockStartDate } from './constants';
import { launchPlans } from './launchPlans';
import { workflows } from './workflows';

export function defaultWorkflowExecutionMetadata(): ExecutionMetadata {
return {
mode: Admin.ExecutionMetadata.ExecutionMode.MANUAL,
principal: 'sdk',
nesting: 0
};
}

export function emptyLiteralMap(): LiteralMap {
return { literals: {} };
}

const basic: Execution = {
id: {
project: 'flytetest',
domain: 'development',
name: 'abc123'
},
spec: {
launchPlan: { ...launchPlans.basic.id },
inputs: emptyLiteralMap(),
metadata: defaultWorkflowExecutionMetadata(),
notifications: {
notifications: []
}
},
closure: {
computedInputs: emptyLiteralMap(),
createdAt: dateToTimestamp(mockStartDate),
duration: millisecondsToDuration(defaultWorkflowExecutionDuration),
phase: WorkflowExecutionPhase.SUCCEEDED,
startedAt: dateToTimestamp(mockStartDate),
workflowId: { ...workflows.basic.id }
}
};

export const workflowExecutions = {
basic
};
15 changes: 15 additions & 0 deletions src/mocks/data/workflows.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Core } from 'flyteidl';
import { Workflow } from 'models/Workflow/types';

// TODO:
const basic: Workflow = {
id: {
resourceType: Core.ResourceType.WORKFLOW,
project: 'flytetest',
domain: 'development',
name: 'Basic',
version: 'abc123'
}
};

export const workflows = { basic };
10 changes: 10 additions & 0 deletions src/mocks/getDefaultData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { RequestHandlersList } from 'msw/lib/types/setupWorker/glossary';
import { workflowExecutions } from './data/workflowExecutions';
import { workflowExecutionHandler } from './handlers';

export function getDefaultData(): RequestHandlersList {
const workflowExecutionHandlers = Object.values(workflowExecutions).map(
workflowExecutionHandler
);
return [...workflowExecutionHandlers];
}
102 changes: 102 additions & 0 deletions src/mocks/handlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { Admin } from 'flyteidl';
import {
EncodableType,
encodeProtoPayload,
Execution,
NameIdentifierScope,
NodeExecution,
Project,
Workflow
} from 'models';
import {
makeExecutionPath,
makeNodeExecutionListPath,
makeNodeExecutionPath
} from 'models/Execution/utils';
import { makeWorkflowPath } from 'models/Workflow/utils';
import { ResponseResolver, rest } from 'msw';
import { setupServer } from 'msw/lib/types/node';
import { RestContext } from 'msw/lib/types/rest';
import { apiPath } from './utils';

export function adminEntityResponder(
data: any,
encodeType: EncodableType<any>
): ResponseResolver<any, RestContext> {
const buffer = encodeProtoPayload(data, encodeType);
const contentLength = buffer.byteLength.toString();
return (_, res, ctx) =>
res(
ctx.set('Content-Type', 'application/octet-stream'),
ctx.set('Content-Length', contentLength),
ctx.body(buffer)
);
}

export function workflowExecutionHandler(data: Partial<Execution>) {
return rest.get(
apiPath(makeExecutionPath(data.id!)),
adminEntityResponder(data, Admin.Execution)
);
}

export function workflowHandler(data: Partial<Workflow>) {
return rest.get(
apiPath(makeWorkflowPath(data.id!)),
adminEntityResponder(data, Admin.Workflow)
);
}

export function nodeExecutionHandler(data: Partial<NodeExecution>) {
return rest.get(
apiPath(makeNodeExecutionPath(data.id!)),
adminEntityResponder(data, Admin.NodeExecution)
);
}

// TODO: pagination responder that respects limit/token?
export function nodeExecutionListHandler(
scope: NameIdentifierScope,
data: Partial<NodeExecution>[]
) {
return rest.get(
apiPath(makeNodeExecutionListPath(scope)),
adminEntityResponder(
{
nodeExecutions: data
},
Admin.NodeExecutionList
)
);
}

export function projectListHandler(data: Project[]) {
return rest.get(
apiPath('/projects'),
adminEntityResponder({ projects: data }, Admin.Projects)
);
}

export interface BoundAdminServer {
insertNodeExecution(data: Partial<NodeExecution>): void;
insertNodeExecutionList(
scope: NameIdentifierScope,
data: Partial<NodeExecution>[]
): void;
insertProjects(data: Project[]): void;
insertWorkflow(data: Partial<Workflow>): void;
insertWorkflowExecution(data: Partial<Execution>): void;
}

export function bindHandlers({
use
}: ReturnType<typeof setupServer>): BoundAdminServer {
return {
insertNodeExecution: data => use(nodeExecutionHandler(data)),
insertNodeExecutionList: (scope, data) =>
use(nodeExecutionListHandler(scope, data)),
insertProjects: data => use(projectListHandler(data)),
insertWorkflow: data => use(workflowHandler(data)),
insertWorkflowExecution: data => use(workflowExecutionHandler(data))
};
}
7 changes: 7 additions & 0 deletions src/mocks/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { setupServer } from 'msw/node';
import { getDefaultData } from './getDefaultData';
import { bindHandlers } from './handlers';

const server = setupServer(...getDefaultData());
const handlers = bindHandlers(server);
export const mockServer = { ...server, ...handlers };
5 changes: 5 additions & 0 deletions src/mocks/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { apiPrefix } from 'models/AdminEntity/constants';

export function apiPath(path: string) {
return `${apiPrefix}${path}`;
}
2 changes: 2 additions & 0 deletions src/models/AdminEntity/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { RequestConfig } from './types';

export const apiPrefix = '/api/v1';

export const limits = {
DEFAULT: 25,
/** The admin API requires a limit value for all list endpoints, but does not
Expand Down
1 change: 0 additions & 1 deletion src/models/AdminEntity/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './AdminApiQuery';
export * from './AdminEntity';
export * from './constants';
export * from './types';
export * from './utils';
Loading