Skip to content

Commit

Permalink
test: fix tests + add new ones
Browse files Browse the repository at this point in the history
Signed-off-by: Nastya <55718143+anrusina@users.noreply.github.com>
  • Loading branch information
anrusina committed May 25, 2022
1 parent 6412608 commit 9dd46b9
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 30 deletions.
6 changes: 3 additions & 3 deletions packages/composites/ui-atoms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.0.1-rc.2",
"description": "Flyteconsole UI atoms, which didn't plan to be published and would be consumed as is internally",
"main": "./dist/index.js",
"module": "./lib/esm/index.js",
"types": "./lib/esm/index.d.ts",
"module": "./lib/index.js",
"types": "./lib/index.d.ts",
"license": "Apache-2.0",
"private": false,
"publishConfig": {
Expand All @@ -13,7 +13,7 @@
},
"scripts": {
"build": "yarn build:esm && yarn build:cjs",
"build:esm": "tsc --module esnext --outDir lib/esm",
"build:esm": "tsc --module esnext --outDir lib",
"build:cjs": "tsc",
"test": "NODE_ENV=test jest"
},
Expand Down
6 changes: 3 additions & 3 deletions packages/plugins/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.0.1-rc.2",
"description": "Flyteconsole Components module, which is published as npm package and can be consumed by 3rd parties",
"main": "./dist/index.js",
"module": "./lib/esm/index.js",
"types": "./lib/esm/index.d.ts",
"module": "./lib/index.js",
"types": "./lib/index.d.ts",
"license": "Apache-2.0",
"private": false,
"publishConfig": {
Expand All @@ -13,7 +13,7 @@
},
"scripts": {
"build": "yarn build:esm && yarn build:cjs",
"build:esm": "tsc --module esnext --outDir lib/esm --project ./tsconfig.build.json",
"build:esm": "tsc --module esnext --outDir lib --project ./tsconfig.build.json",
"build:cjs": "tsc --project ./tsconfig.build.json",
"test": "NODE_ENV=test jest"
},
Expand Down
8 changes: 4 additions & 4 deletions packages/plugins/flyte-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.0.2-rc1",
"description": "FlyteConsole plugin to allow access FlyteAPI",
"main": "./dist/index.js",
"module": "./lib/esm/index.js",
"types": "./lib/esm/index.d.ts",
"module": "./lib/index.js",
"types": "./lib/index.d.ts",
"license": "Apache-2.0",
"private": false,
"publishConfig": {
Expand All @@ -14,9 +14,9 @@
"scripts": {
"clean": "rm -rf dist && rm -rf lib",
"build": "yarn build:esm && yarn build:cjs",
"build:esm": "tsc --module esnext --outDir lib/esm --project ./tsconfig.build.json",
"build:esm": "tsc --module esnext --outDir lib --project ./tsconfig.build.json",
"build:cjs": "tsc --project ./tsconfig.build.json",
"push:update": "yarn clean && yarn build:esm && yarn publish",
"push:update": "yarn clean && yarn build && yarn publish",
"test": "NODE_ENV=test jest"
},
"dependencies": {
Expand Down
47 changes: 47 additions & 0 deletions packages/plugins/flyte-api/src/ApiProvider/apiProvider.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { FlyteApiProvider, useFlyteApi } from '.';
import { AdminEndpoint } from '../utils/constants';
import { getLoginUrl } from './login';

const MockCoponent = () => {
const context = useFlyteApi();

return (
<>
<div>{context.getProfileUrl()}</div>
<div>{context.getAdminApiUrl('/magic')}</div>
<div>{context.getLoginUrl()}</div>
</>
);
};

describe('fltyte-api/ApiProvider', () => {
it('getLoginUrl properly adds redirect url', () => {
const result = getLoginUrl(AdminEndpoint.Version, `http://some.nonsense`);
expect(result).toEqual('/version/login?redirect_url=http://some.nonsense');
});

it('If FlyteApiContext is not defined, returned URL uses default value', () => {
const { getAllByText } = render(<MockCoponent />);
expect(getAllByText('#').length).toBe(3);
});

it('If FlyteApiContext is defined, but flyteApiDomain is not point to localhost', () => {
const { getByText } = render(
<FlyteApiProvider>
<MockCoponent />
</FlyteApiProvider>,
);
expect(getByText('http://localhost/me')).toBeInTheDocument();
});

it('If FlyteApiContext provides flyteApiDomain value', () => {
const { getByText } = render(
<FlyteApiProvider flyteApiDomain="https://some.domain.here">
<MockCoponent />
</FlyteApiProvider>,
);
expect(getByText('https://some.domain.here/me')).toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion packages/plugins/flyte-api/src/ApiProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface FlyteApiContextState {
loginStatus: LoginStatus;
getLoginUrl: (redirect?: string) => string;
getProfileUrl: () => string;
getAdminApiUrl: (endpoint: AdminEndpoint) => string;
getAdminApiUrl: (endpoint: AdminEndpoint | string) => string;
}

const FlyteApiContext = createContext<FlyteApiContextState>({
Expand Down
65 changes: 65 additions & 0 deletions packages/plugins/flyte-api/src/utils/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { getAdminApiUrl, getEndpointUrl } from '.';
import { AdminEndpoint, RawEndpoint } from './constants';
import { transformRequestError } from './errors';
import { isObject } from './nodeChecks';

describe('flyte-api/utils', () => {
it('getEndpointUrl properly uses local or admin domain', () => {
// when admin domain is not provided - uses localhost
let result = getEndpointUrl(RawEndpoint.Profile);
expect(result).toEqual('http://localhost/me');

// when admin domain is empty - uses localhost
result = getEndpointUrl(RawEndpoint.Profile, '');
expect(result).toEqual('http://localhost/me');

// when admin domain is empty - uses localhost
result = getEndpointUrl(RawEndpoint.Profile, '');
expect(result).toEqual('http://localhost/me');

// when admin domain provided - uses it
result = getEndpointUrl(RawEndpoint.Profile, 'https://admin.domain.io');
expect(result).toEqual('https://admin.domain.io/me');
});

it('getAdminApiUrl properly adds api/v1 prefix', () => {
// when admin domain is not provided - uses localhost
let result = getAdminApiUrl(AdminEndpoint.Version);
expect(result).toEqual('http://localhost/api/v1/version');

result = getAdminApiUrl('execution?=filter', 'https://admin.domain.io');
expect(result).toEqual('https://admin.domain.io/api/v1/execution?=filter');
});

it('isObject properly identifies objects', () => {
// Not an objects
expect(isObject(null)).toBeFalsy();
expect(isObject(undefined)).toBeFalsy();
expect(isObject(3)).toBeFalsy();
expect(isObject('abc')).toBeFalsy();
expect(isObject(true)).toBeFalsy();

// Objects
expect(isObject({ hi: 'there' })).toBeTruthy();
expect(isObject([])).toBeTruthy();
expect(isObject({})).toBeTruthy();
});

it('transformRequestError', () => {
// no status - return item as is
let result = transformRequestError({ message: 'default' }, '');
expect(result.message).toEqual('default');

// 401 - Unauthorised
result = transformRequestError({ response: { status: 401 }, message: 'default' }, '');
expect(result.message).toEqual('User is not authorized to view this resource');

// 404 - Not Found
result = transformRequestError({ response: { status: 404 }, message: 'default' }, '');
expect(result.message).toEqual('The requested item could not be found');

// unnown status - return item as is
result = transformRequestError({ response: { status: 502 }, message: 'default' }, '');
expect(result.message).toEqual('default');
});
});
2 changes: 2 additions & 0 deletions packages/zapp/console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"axios-mock-adapter": "^1.16.0",
"babel-loader": "^8.2.5",
"babel-polyfill": "^6.26.0",
"camelcase-keys": "^7.0.2",
"classnames": "^2.3.1",
"compression-webpack-plugin": "^9.2.0",
"contrast": "^1.0.1",
Expand Down Expand Up @@ -146,6 +147,7 @@
"resolve-url-loader": "^5.0.0",
"semantic-release": "^17.2.3",
"shallowequal": "^1.1.0",
"snakecase-keys": "^5.4.2",
"source-map-loader": "^3.0.1",
"ts-loader": "^9.2.6",
"ts-node": "^8.0.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import { APIContext } from 'components/data/apiContext';
import { useUserProfile } from 'components/hooks/useUserProfile';
import { mockAPIContextValue } from 'components/data/__mocks__/apiContext';
import { FetchableData } from 'components/hooks/types';
import { loadedFetchable } from 'components/hooks/__mocks__/fetchableData';
import { FilterOperationName } from 'models/AdminEntity/types';
import { getUserProfile, listNamedEntities } from 'models/Common/api';
import { listNamedEntities } from 'models/Common/api';
import {
NamedEntity,
NamedEntityIdentifier,
Expand All @@ -27,6 +30,7 @@ const sampleUserProfile: UserProfile = {
subject: 'subject',
} as UserProfile;

jest.mock('components/hooks/useUserProfile');
jest.mock('notistack', () => ({
useSnackbar: () => ({ enqueueSnackbar: jest.fn() }),
}));
Expand All @@ -41,10 +45,10 @@ describe('ProjectTasks', () => {
let tasks: NamedEntity[];
let queryClient: QueryClient;
let mockListNamedEntities: jest.Mock<ReturnType<typeof listNamedEntities>>;
let mockGetUserProfile: jest.Mock<ReturnType<typeof getUserProfile>>;
const mockUseUserProfile = useUserProfile as jest.Mock<FetchableData<UserProfile | null>>;

beforeEach(() => {
mockGetUserProfile = jest.fn().mockResolvedValue(null);
mockUseUserProfile.mockReturnValue(loadedFetchable(null, jest.fn()));
queryClient = createTestQueryClient();
tasks = ['MyTask', 'MyOtherTask'].map((name) => createTask({ domain, name, project }));
mockListNamedEntities = jest.fn().mockResolvedValue({ entities: tasks });
Expand All @@ -60,10 +64,7 @@ describe('ProjectTasks', () => {
render(
<QueryClientProvider client={queryClient}>
<APIContext.Provider
value={mockAPIContextValue({
listNamedEntities: mockListNamedEntities,
getUserProfile: mockGetUserProfile,
})}
value={mockAPIContextValue({ listNamedEntities: mockListNamedEntities })}
>
<ProjectTasks projectId={project} domainId={domain} />
</APIContext.Provider>
Expand Down Expand Up @@ -91,7 +92,7 @@ describe('ProjectTasks', () => {
});

it('should display checkbox if user login', async () => {
mockGetUserProfile.mockResolvedValue(sampleUserProfile);
mockUseUserProfile.mockReturnValue(loadedFetchable(sampleUserProfile, jest.fn()));
const { getAllByRole } = renderComponent();
await waitFor(() => {});
const checkboxes = getAllByRole(/checkbox/i) as HTMLInputElement[];
Expand All @@ -101,7 +102,7 @@ describe('ProjectTasks', () => {
});

it('should display archive button', async () => {
mockGetUserProfile.mockResolvedValue(sampleUserProfile);
mockUseUserProfile.mockReturnValue(loadedFetchable(sampleUserProfile, jest.fn()));
const { getByText, getAllByTitle, findAllByText } = renderComponent();
await waitFor(() => {});

Expand Down Expand Up @@ -130,7 +131,7 @@ describe('ProjectTasks', () => {
});

it('clicking show archived should hide active tasks', async () => {
mockGetUserProfile.mockResolvedValue(sampleUserProfile);
mockUseUserProfile.mockReturnValue(loadedFetchable(sampleUserProfile, jest.fn()));
const { getByText, queryByText, getAllByRole } = renderComponent();
await waitFor(() => {});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { fireEvent, render, waitFor } from '@testing-library/react';
import { APIContext } from 'components/data/apiContext';
import { mockAPIContextValue } from 'components/data/__mocks__/apiContext';
import { FetchableData } from 'components/hooks/types';
import { useUserProfile } from 'components/hooks/useUserProfile';
import { loadedFetchable } from 'components/hooks/__mocks__/fetchableData';
import { FilterOperationName } from 'models/AdminEntity/types';
import { getUserProfile, listNamedEntities } from 'models/Common/api';
import { listNamedEntities } from 'models/Common/api';
import { NamedEntity, UserProfile } from 'models/Common/types';
import { NamedEntityState } from 'models/enums';
import * as React from 'react';
Expand All @@ -16,6 +19,7 @@ const sampleUserProfile: UserProfile = {
subject: 'subject',
} as UserProfile;

jest.mock('components/hooks/useUserProfile');
jest.mock('notistack', () => ({
useSnackbar: () => ({ enqueueSnackbar: jest.fn() }),
}));
Expand All @@ -26,10 +30,11 @@ describe('ProjectWorkflows', () => {
let workflowNames: NamedEntity[];
let queryClient: QueryClient;
let mockListNamedEntities: jest.Mock<ReturnType<typeof listNamedEntities>>;
let mockGetUserProfile: jest.Mock<ReturnType<typeof getUserProfile>>;

const mockUseUserProfile = useUserProfile as jest.Mock<FetchableData<UserProfile | null>>;

beforeEach(() => {
mockGetUserProfile = jest.fn().mockResolvedValue(null);
mockUseUserProfile.mockReturnValue(loadedFetchable(null, jest.fn()));
queryClient = createTestQueryClient();
workflowNames = ['MyWorkflow', 'MyOtherWorkflow'].map((name) =>
createWorkflowName({ domain, name, project }),
Expand All @@ -41,10 +46,7 @@ describe('ProjectWorkflows', () => {
render(
<QueryClientProvider client={queryClient}>
<APIContext.Provider
value={mockAPIContextValue({
listNamedEntities: mockListNamedEntities,
getUserProfile: mockGetUserProfile,
})}
value={mockAPIContextValue({ listNamedEntities: mockListNamedEntities })}
>
<ProjectWorkflows projectId={project} domainId={domain} />
</APIContext.Provider>
Expand All @@ -71,7 +73,7 @@ describe('ProjectWorkflows', () => {
});

it('should display checkbox if user login', async () => {
mockGetUserProfile.mockResolvedValue(sampleUserProfile);
mockUseUserProfile.mockReturnValue(loadedFetchable(sampleUserProfile, jest.fn()));
const { getAllByRole } = renderComponent();
await waitFor(() => {});
const checkboxes = getAllByRole(/checkbox/i) as HTMLInputElement[];
Expand All @@ -82,7 +84,7 @@ describe('ProjectWorkflows', () => {

/** user doesn't have its own workflow */
it('clicking show archived should hide active workflows', async () => {
mockGetUserProfile.mockResolvedValue(sampleUserProfile);
mockUseUserProfile.mockReturnValue(loadedFetchable(sampleUserProfile, jest.fn()));
const { getByText, queryByText, getAllByRole } = renderComponent();
await waitFor(() => {});
const checkboxes = getAllByRole(/checkbox/i) as HTMLInputElement[];
Expand Down

0 comments on commit 9dd46b9

Please sign in to comment.