Skip to content

Commit ddab982

Browse files
Fixing unit tests
1 parent da34a87 commit ddab982

File tree

3 files changed

+111
-85
lines changed

3 files changed

+111
-85
lines changed

desktop/core/src/desktop/js/apps/admin/Components/utils.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ export const SERVER_LOGS_API_URL = '/api/v1/logs';
1818
export const CHECK_CONFIG_EXAMPLES_API_URL = '/api/v1/check_config';
1919
export const ANALYTICS_PREFERENCES_API_URL = '/about/update_preferences';
2020
export const INSTALL_APP_EXAMPLES_API_URL = '/api/v1/install_app_examples';
21+
export const INSTALL_AVAILABLE_EXAMPLES_API_URL = '/api/v1/available_app_examples';

desktop/core/src/desktop/js/apps/admin/Overview/Examples.tsx

+44-24
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,20 @@
1414
// See the License for the specific language governing permissions and
1515
// limitations under the License.
1616

17-
import React, { useState } from 'react';
17+
import React, { useState, useEffect } from 'react';
1818
import { Button } from 'antd';
1919
import { DownloadOutlined } from '@ant-design/icons';
20-
import { INSTALL_APP_EXAMPLES_API_URL } from '../Components/utils';
21-
import { post } from '../../../api/utils';
20+
import Loading from 'cuix/dist/components/Loading';
21+
import {
22+
INSTALL_APP_EXAMPLES_API_URL,
23+
INSTALL_AVAILABLE_EXAMPLES_API_URL
24+
} from '../Components/utils';
25+
import { get, post } from '../../../api/utils';
2226
import huePubSub from '../../../utils/huePubSub';
2327
import { i18nReact } from '../../../utils/i18nReact';
2428
import './Overview.scss';
2529

26-
const exampleApps = [
27-
{ id: 'hive', name: 'Hive', old_name: 'beeswax' },
28-
{ id: 'impala', name: 'Impala' },
29-
{ id: 'hbase', name: 'Hbase Browser' },
30-
{ id: 'pig', name: 'Pig Editor' },
31-
{ id: 'oozie', name: 'Oozie Editor/Dashboard' },
32-
{ id: 'spark', name: 'Spark', old_name: 'notebook' },
30+
const exampleAppsWithData = [
3331
{ id: 'search', name: 'Solr Search', data: ['log_analytics_demo', 'twitter_demo', 'yelp_demo'] }
3432
];
3533

@@ -41,14 +39,33 @@ type InstallExamplesResponse = {
4139
const Examples = (): JSX.Element => {
4240
const { t } = i18nReact.useTranslation();
4341
const [installingAppId, setInstallingAppId] = useState<string>('');
42+
const [availableApps, setAvailableApps] = useState<any[]>([]);
43+
const [loading, setLoading] = useState<boolean>(true);
44+
45+
useEffect(() => {
46+
const fetchAvailableApps = async () => {
47+
setLoading(true);
48+
try {
49+
const response = await get(INSTALL_AVAILABLE_EXAMPLES_API_URL, {});
50+
setAvailableApps(response.apps);
51+
} catch (error) {
52+
console.error('Error fetching available app examples:', error);
53+
} finally {
54+
setLoading(false);
55+
}
56+
};
57+
58+
fetchAvailableApps();
59+
}, []);
4460

4561
const handleInstall = async exampleApp => {
4662
setInstallingAppId(exampleApp.id);
4763
const url = INSTALL_APP_EXAMPLES_API_URL;
4864
const data = { app_name: exampleApp.id };
4965

50-
if (exampleApp.data) {
51-
data['data'] = exampleApp.data;
66+
const appWithExtraData = exampleAppsWithData.find(app => app.id === exampleApp.id);
67+
if (appWithExtraData && appWithExtraData.data) {
68+
data['data'] = appWithExtraData.data;
5269
}
5370

5471
post<InstallExamplesResponse>(url, data)
@@ -70,18 +87,21 @@ const Examples = (): JSX.Element => {
7087
return (
7188
<div className="overview-examples">
7289
<h3>{t('Install some data examples')}</h3>
73-
{exampleApps.map(exampleApp => (
74-
<div key={exampleApp.id}>
75-
<Button
76-
type="link"
77-
onClick={() => handleInstall(exampleApp)}
78-
disabled={installingAppId === exampleApp.id}
79-
icon={<DownloadOutlined />}
80-
>
81-
{installingAppId === exampleApp.id ? t('Installing...') : exampleApp.name}
82-
</Button>
83-
</div>
84-
))}
90+
{loading ? (<Loading spinning={loading} />
91+
) : (
92+
Object.entries(availableApps).map(([appId, appName]) => (
93+
<div key={appId}>
94+
<Button
95+
type="link"
96+
onClick={() => handleInstall({ id: appId, name: appName })}
97+
disabled={installingAppId === appId}
98+
icon={<DownloadOutlined />}
99+
>
100+
{installingAppId === appId ? t('Installing...') : appName}
101+
</Button>
102+
</div>
103+
))
104+
)}
85105
</div>
86106
);
87107
};

desktop/core/src/desktop/js/apps/admin/Overview/OverviewTab.test.tsx

+66-61
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,15 @@ import Overview from './OverviewTab';
2121
import * as hueConfigModule from '../../../config/hueConfig';
2222
import Examples from './Examples';
2323
import Analytics from './Analytics';
24-
import { post } from '../../../api/utils';
24+
import {
25+
INSTALL_APP_EXAMPLES_API_URL,
26+
INSTALL_AVAILABLE_EXAMPLES_API_URL
27+
} from '../Components/utils';
28+
import { get, post } from '../../../api/utils';
2529

2630
jest.mock('../../../api/utils', () => ({
27-
post: jest.fn()
31+
post: jest.fn(),
32+
get: jest.fn()
2833
}));
2934

3035
jest.mock('./ConfigStatus', () => () => <div>MockedConfigStatusComponent</div>);
@@ -57,23 +62,6 @@ describe('OverviewTab', () => {
5762
expect(screen.queryByText('MockedAnalyticsComponent')).not.toBeInTheDocument();
5863
});
5964

60-
test('shows the trademark text', () => {
61-
render(<Overview />);
62-
expect(
63-
screen.getByText('Hue and the Hue logo are trademarks of Cloudera, Inc.')
64-
).toBeInTheDocument();
65-
});
66-
67-
test('it should not render Overview for non-admin users', () => {
68-
(hueConfigModule.getLastKnownConfig as jest.Mock).mockReturnValue({
69-
hue_config: { is_admin: false }
70-
});
71-
72-
const { queryByText } = render(<Overview />);
73-
const trademarkText = queryByText('Hue and the Hue logo are trademarks of Cloudera, Inc.');
74-
expect(trademarkText).toBeNull();
75-
});
76-
7765
describe('Analytics Component', () => {
7866
test('renders Analytics tab and can interact with the checkbox', async () => {
7967
(post as jest.Mock).mockResolvedValue({ status: 0, message: 'Success' });
@@ -94,52 +82,69 @@ describe('OverviewTab', () => {
9482
});
9583

9684
describe('Examples component', () => {
97-
const exampleApps = [
98-
{ id: 'hive', name: 'Hive', old_name: 'beeswax' },
99-
{ id: 'impala', name: 'Impala' },
100-
{
101-
id: 'search',
102-
name: 'Solr Search',
103-
data: ['log_analytics_demo', 'twitter_demo', 'yelp_demo']
104-
},
105-
{ id: 'spark', name: 'Spark', old_name: 'notebook' },
106-
{ id: 'oozie', name: 'Oozie Editor/Dashboard' },
107-
{ id: 'hbase', name: 'Hbase Browser' },
108-
{ id: 'pig', name: 'Pig Editor' }
109-
];
110-
111-
const resolvedValue = { status: 0, message: 'Success' };
112-
113-
exampleApps.forEach(appData => {
114-
test(`clicking the install button for '${appData.name}' makes an API call to '/api/v1/install_app_examples'`, async () => {
115-
(post as jest.Mock).mockResolvedValue(resolvedValue);
116-
render(<Examples />);
11785

118-
const button = screen.getByText(appData.name);
119-
fireEvent.click(button);
86+
const availableAppsResponse = {
87+
apps: {
88+
hive: 'Hive',
89+
impala: 'Impala'
90+
}
91+
};
92+
beforeEach(() => {
93+
(get as jest.Mock).mockImplementation(url => {
94+
if (url === INSTALL_AVAILABLE_EXAMPLES_API_URL) {
95+
return Promise.resolve(availableAppsResponse);
96+
}
97+
return Promise.reject();
98+
});
99+
100+
(post as jest.Mock).mockImplementation(() => Promise.resolve({ status: 0, message: 'Success' }));
101+
});
102+
103+
afterEach(() => {
104+
jest.clearAllMocks();
105+
});
106+
107+
test('fetch and display available apps', async () => {
108+
render(<Examples />);
109+
110+
await waitFor(() => {
111+
expect(get).toHaveBeenCalledWith(INSTALL_AVAILABLE_EXAMPLES_API_URL, {});
112+
Object.entries(availableAppsResponse.apps).forEach(([appId, appName]) => {
113+
expect(screen.getByText(appName)).toBeInTheDocument();
114+
});
115+
});
116+
});
117+
118+
test('post to install app example when the install button is clicked', async () => {
119+
render(<Examples />);
120+
121+
await waitFor(() => {
122+
expect(get).toHaveBeenCalledWith(INSTALL_AVAILABLE_EXAMPLES_API_URL, {});
123+
Object.entries(availableAppsResponse.apps).forEach(([appId, appName]) => {
124+
expect(screen.getByText(appName)).toBeInTheDocument();
125+
});
126+
});
127+
128+
const installButton = screen.getByText('Hive');
129+
fireEvent.click(installButton);
130+
131+
await waitFor(() => {
132+
expect(post).toHaveBeenCalledWith(
133+
INSTALL_APP_EXAMPLES_API_URL,
134+
{ app_name: 'hive' }
135+
);
136+
});
137+
expect(installButton.textContent).toContain('Hive');
138+
}
139+
);
140+
141+
test('display a confirmation message after a successful install', async () => {
142+
render(<Examples />);
120143

144+
const appName = 'Hive';
121145
await waitFor(() => {
122-
if (appData.data) {
123-
expect(post).toHaveBeenCalledWith(
124-
'/api/v1/install_app_examples',
125-
{
126-
app_name: appData.id,
127-
data: appData.data
128-
},
129-
expect.anything()
130-
);
131-
} else {
132-
expect(post).toHaveBeenCalledWith(
133-
'/api/v1/install_app_examples',
134-
{
135-
app_name: appData.id
136-
},
137-
expect.anything()
138-
);
139-
}
146+
expect(screen.getByText(appName)).toBeInTheDocument();
140147
});
141-
(post as jest.Mock).mockClear();
142148
});
143149
});
144150
});
145-
});

0 commit comments

Comments
 (0)