Skip to content

Commit

Permalink
Merge pull request #220 from kbase/URO-211
Browse files Browse the repository at this point in the history
URO-211 part A - support for kbase service mocking
  • Loading branch information
eapearson authored Jun 25, 2024
2 parents afe73d5 + 5674e8d commit 0a522b0
Show file tree
Hide file tree
Showing 8 changed files with 477 additions and 37 deletions.
19 changes: 14 additions & 5 deletions src/common/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { kbaseBaseQuery } from './utils/kbaseBaseQuery';
import { createApi } from '@reduxjs/toolkit/query/react';
import { kbaseBaseQuery } from './utils/kbaseBaseQuery';

const baseUrl =
process.env.NODE_ENV === 'development'
? 'http://localhost:3000/'
: `https://${process.env.REACT_APP_KBASE_DOMAIN}`;
export const baseUrl = (() => {
const nodeEnv = process.env.NODE_ENV;
if (nodeEnv === 'development') {
return 'http://localhost:3000/';
} else if (nodeEnv === 'test') {
// This prevents API calls from attempting to talk to live servers on CI.
// Tests which utilize actual api calls should either mock the endpoint on
// localhost, or mock the api itself.
return 'http://localhost/';
} else {
return `https://${process.env.REACT_APP_KBASE_DOMAIN}/`;
}
})();

export const baseApi = createApi({
reducerPath: 'combinedApi',
Expand Down
65 changes: 41 additions & 24 deletions src/features/icons/AppCellIcon.test.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,47 @@
import AppCellIcon from './AppCellIcon';
import { createTestStore } from '../../app/store';
import { Provider } from 'react-redux';
import { render, waitFor } from '@testing-library/react';
import fetchMock from 'jest-fetch-mock';
import { FetchMock } from 'jest-fetch-mock/types';
import { Provider } from 'react-redux';
import { createTestStore } from '../../app/store';
import { makeKBaseServices } from '../../test/kbaseServiceMock';
import AppCellIcon from './AppCellIcon';
import { AppTag } from './iconSlice';

test('AppCellIcon renders initial loading icon', () => {
const { container } = render(
<Provider store={createTestStore()}>
<AppCellIcon appId="SomeModule.someApp" appTag={AppTag.release} />
</Provider>
);
expect(container.querySelector('svg[data-icon="spinner"]')).not.toBeNull();
});
describe('The AppCellIcon', () => {
let mockService: FetchMock;

beforeEach(() => {
fetchMock.enableMocks();
mockService = makeKBaseServices();
});

afterEach(() => {
mockService.mockClear();
fetchMock.disableMocks();
});

test('renders initial loading icon', () => {
const { container } = render(
<Provider store={createTestStore()}>
<AppCellIcon appId="SomeModule.someApp" appTag={AppTag.release} />
</Provider>
);
expect(container.querySelector('svg[data-icon="spinner"]')).not.toBeNull();
});

test('AppCellIcon renders an icon after the callback finishes', async () => {
const { container } = render(
<Provider store={createTestStore()}>
<AppCellIcon appId="SomeModule.someApp" appTag={AppTag.beta} />
</Provider>
);
await waitFor(() => {
expect(
container.querySelector('svg[data-icon="spinner"]')
).not.toBeInTheDocument();
expect(
container.querySelector('svg[data-icon="cube"]')
).toBeInTheDocument();
test('renders an icon after the callback finishes', async () => {
const { container } = render(
<Provider store={createTestStore()}>
<AppCellIcon appId="SomeModule.someApp" appTag={AppTag.beta} />
</Provider>
);
await waitFor(() => {
expect(
container.querySelector('svg[data-icon="spinner"]')
).not.toBeInTheDocument();
expect(
container.querySelector('svg[data-icon="cube"]')
).toBeInTheDocument();
});
});
});
26 changes: 18 additions & 8 deletions src/features/profile/profileSlice.test.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
// Start a new test file for profileSlice specifically.
import { render, waitFor } from '@testing-library/react';
import fetchMock from 'jest-fetch-mock';
import { FetchMock } from 'jest-fetch-mock/types';
import { ErrorBoundary } from 'react-error-boundary';
import { Provider } from 'react-redux';

import { createTestStore } from '../../app/store';

import { makeKBaseServices } from '../../test/kbaseServiceMock';
import { useLoggedInProfileUser } from './profileSlice';

let testStore = createTestStore({});

describe('useLoggedInProfileUser', () => {
let mockService: FetchMock;

beforeEach(() => {
testStore = createTestStore({});
fetchMock.enableMocks();
mockService = makeKBaseServices();
});

afterEach(() => {
mockService.mockClear();
fetchMock.disableMocks();
});

test('useLoggedInProfileUser sets loggedInProfile on success with valid username', async () => {
test('sets loggedInProfile on success with valid username', async () => {
const Component = () => {
useLoggedInProfileUser('dlyon');
useLoggedInProfileUser('kbaseuitest');
return <></>;
};
render(
Expand All @@ -25,18 +35,18 @@ describe('useLoggedInProfileUser', () => {
);
await waitFor(() =>
expect(testStore.getState().profile.loggedInProfile?.user.username).toBe(
'dlyon'
'kbaseuitest'
)
);
});

test('useLoggedInProfileUser throws error when called with invalid username', async () => {
test('throws error when called with invalid username', async () => {
const onErr = jest.fn();
const consoleError = jest.spyOn(console, 'error');
// eslint-disable-next-line @typescript-eslint/no-empty-function
consoleError.mockImplementation(() => {});
const Component = () => {
useLoggedInProfileUser('!!!Iamnotause');
useLoggedInProfileUser('not_a_user');
return <></>;
};
render(
Expand Down
55 changes: 55 additions & 0 deletions src/test/data/narrative_method_store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Test data from the NarrativeMethodStore service.
*
* All data is from live calls to the CI instance of NMS in June 2024.
*
* All data represents just the data needed for testing. For instance, it is
* unwrapped from the rpc structure and the results array.
*/

/**
* Result of a call to the "NarrativeMethodStore.status" method
*
* curl -X POST https://ci.kbase.us/services/narrative_method_store/rpc \
-d '{
"version": "1.1",
"id": "123",
"method": "NarrativeMethodStore.status",
"params": []
}'
*/
export const STATUS_1 = {
git_spec_url: 'https://github.com/kbase/narrative_method_specs_ci',
git_spec_branch: 'master',
git_spec_commit:
'commit 042b36d193054ccb42f7e3a89d35c2a9989ecceb\nMerge: 7c58bbd 952d3d4\nAuthor: Bill Riehl <[email protected]>\nDate: Wed Nov 10 12:41:27 2021 -0800\n\n Merge pull request #110 from qzzhang/master\n \n Added the KBaseStructure structure types\n',
update_interval: '5',
};

/**
* An example app "brief info". The data represents just the brief info for the
* single app requested, rather than the array returned in the actual result.
*
* curl -X POST https://ci.kbase.us/services/narrative_method_store/rpc \
-d '{
"version": "1.1",
"id": "123",
"method": "NarrativeMethodStore.get_method_brief_info",
"params": [{"ids": ["NarrativeViewers/view_assembly"]}]
}'
*/
export const VIEW_ASSEMBLY_BRIEF_INFO_1 = {
id: 'NarrativeViewers/view_assembly',
module_name: 'NarrativeViewers',
git_commit_hash: '0851ff66474b615dcf447499d133885a09adc862',
name: 'View Assembly',
ver: '1.0.8',
subtitle: 'View and explore an Assembly object in your workspace. [5]',
tooltip: 'View and explore an Assembly in your workspace. [5]',
categories: ['viewers'],
authors: [],
input_types: ['KBaseGenomeAnnotations.Assembly', 'KBaseGenomes.ContigSet'],
output_types: [],
app_type: 'viewer',
namespace: 'NarrativeViewers',
};
126 changes: 126 additions & 0 deletions src/test/data/user_profile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* The user profile for the CI test user "kbaseuitest".
*
* This is the result of a call to the user profile service's "UserProfile.get_user_profile" method.
* curl -X POST https://ci.kbase.us/services/user_profile/rpc \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"version": "1.1",
"id": "123",
"method": "UserProfile.get_user_profile",
"params": [["eapearson"]]
}'
*/

export const KBASEUITEST_PROFILE = {
user: {
username: 'kbaseuitest',
realname: 'KBase UI Test User',
},
profile: {
metadata: {
createdBy: 'userprofile_ui_service',
created: '2020-01-06T21:48:12.352Z',
},
preferences: {},
userdata: {
organization: '',
department: '',
affiliations: [
{
title: 'tester',
organization: 'kbase / lbnl',
started: 2020,
ended: 2020,
},
],
city: '',
state: 'California',
postalCode: '',
country: '',
researchStatement:
"Test user account for ui integration tests.\n\nPlease don't modify the profile.\n\nThis **can** be markdown, but who would know?",
gravatarDefault: 'monsterid',
avatarOption: 'gravatar',
researchInterests: [
'Comparative Genomics',
'Genome Annotation',
'Metabolic Modeling',
'Read Processing',
'Sequence Analysis',
],
researchInterestsOther: null,
jobTitleOther: 'My job',
jobTitle: 'Other',
fundingSource: '',
},
synced: {
gravatarHash: 'b4d95f8595104614355e6ee9c4c03e3f',
},
plugins: {
'data-search': {
settings: {
history: {
search: {
history: [
'coli',
'abcde12345',
'Abiotrophi',
'sphaeroides',
'orientalis',
'Abiotrophia',
'marinus',
'Prochlorococcus marinus str. GP2',
'query-compost_hq_bins_blastp_output.Seq',
'SequenceSet',
],
time: {
$numberLong: '1656371918191',
},
},
},
},
},
'jgi-search': {
settings: {
history: {
search: {
history: ['coli', 'blahblah', 'Colin'],
time: {
$numberLong: '1658255057551',
},
},
},
jgiDataTerms: {
agreed: true,
time: {
$numberLong: '1580251462454',
},
},
},
},
'public-search': {
settings: {
history: {
history: [
'prochlorococcus',
'coli',
'orientalis',
'Acetobacter orientalis',
'prochlorococcus marinus',
'AnnotatedGenomeAssembly',
'prochlorococcus marnius',
'Prochlorococcus marinus str. GP2',
'AnnotatedMetagenomeAssembly',
'prochlorococcus unconfirmed',
],
time: {
$numberLong: '1656372755178',
},
},
},
},
},
},
};
Loading

0 comments on commit 0a522b0

Please sign in to comment.