* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
import { differenceBy } from 'lodash';
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
WithAvailableFeaturesProps,
} from './available-features/withAvailableFeatures';
import { ComponentContext } from './componentContext/ComponentContext';
-import PageUnavailableDueToIndexation from './indexation/PageUnavailableDueToIndexation';
import ComponentNav from './nav/component/ComponentNav';
interface Props extends WithAvailableFeaturesProps {
getComponentNavigation({ component: key, branch, pullRequest }),
getComponentData({ component: key, branch, pullRequest }),
]);
+
componentWithQualifier = this.addQualifier({ ...nav, ...component });
} catch (e) {
if (this.mounted) {
this.setState({ component: undefined, loading: false });
}
}
+
return;
}
}
let projectBinding;
+
if (componentWithQualifier.qualifier === ComponentQualifier.Project) {
projectBinding = await getProjectAlmBinding(key).catch(() => undefined);
}
({ current, queue }) => {
if (this.mounted) {
let shouldFetchComponent = false;
+
this.setState(
({ component, currentTask, tasksInProgress }) => {
const newCurrentTask = this.getCurrentTask(current);
if (this.needsAnotherCheck(shouldFetchComponent, component, newTasksInProgress)) {
// Refresh the status as long as there is tasks in progress or no analysis
window.clearTimeout(this.watchStatusTimer);
+
this.watchStatusTimer = window.setTimeout(
() => this.fetchStatus(componentKey),
FETCH_STATUS_WAIT_TIME
}
const isPending = pendingTasks.some((task) => task.status === TaskStatuses.Pending);
+
return {
currentTask: newCurrentTask,
isPending,
const projectBindingErrors = await validateProjectAlmBinding(component.key).catch(
() => undefined
);
+
if (this.mounted) {
this.setState({ projectBindingErrors });
}
if (!pullRequest && !branch) {
return !task.branch && !task.pullRequest;
}
+
if (pullRequest) {
return pullRequest === task.pullRequest;
}
+
if (branch) {
return branch === task.branch;
}
+
return false;
};
const newComponent: Component = { ...state.component, ...changes };
return { component: newComponent };
}
+
return null;
});
}
return <ComponentContainerNotFound />;
}
- if (component?.needIssueSync) {
- return <PageUnavailableDueToIndexation component={component} />;
- }
-
const { currentTask, isPending, projectBinding, projectBindingErrors, tasksInProgress } =
this.state;
+
const isInProgress = tasksInProgress && tasksInProgress.length > 0;
return (
component?.name ?? ''
)}
/>
+
{component &&
!([ComponentQualifier.File, ComponentQualifier.TestFile] as string[]).includes(
component.qualifier
projectBindingErrors={projectBindingErrors}
/>
)}
+
{loading ? (
<div className="page page-limited">
<i className="spinner" />
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
import { shallow } from 'enzyme';
import * as React from 'react';
import { getProjectAlmBinding, validateProjectAlmBinding } from '../../../api/alm-settings';
import { Component } from '../../../types/types';
import handleRequiredAuthorization from '../../utils/handleRequiredAuthorization';
import { ComponentContainer } from '../ComponentContainer';
-import PageUnavailableDueToIndexation from '../indexation/PageUnavailableDueToIndexation';
jest.mock('../../../api/branches', () => {
const { mockMainBranch, mockPullRequest } = jest.requireActual(
'../../../helpers/mocks/branch-like'
);
+
return {
getBranches: jest
.fn()
default: jest.fn(),
}));
+// eslint-disable-next-line react/function-component-definition
const Inner = () => <div />;
beforeEach(() => {
it('changes component', () => {
const wrapper = shallowRender();
+
wrapper.setState({
component: {
qualifier: ComponentQualifier.Project,
});
wrapper.instance().handleComponentChange({ visibility: Visibility.Private });
+
expect(wrapper.state().component).toEqual({
qualifier: ComponentQualifier.Project,
visibility: Visibility.Private,
const component = mockComponent({
breadcrumbs: [{ key: 'foo', name: 'foo', qualifier: ComponentQualifier.Project }],
});
- (getComponentNavigation as jest.Mock).mockResolvedValueOnce({});
- (getComponentData as jest.Mock<any>)
- .mockResolvedValueOnce({ component })
- .mockResolvedValueOnce({ component });
- (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce(undefined).mockResolvedValueOnce({
- alm: AlmKeys.GitHub,
- key: 'foo',
- });
+
+ jest
+ .mocked(getComponentNavigation)
+ .mockResolvedValueOnce({} as unknown as Awaited<ReturnType<typeof getComponentNavigation>>);
+
+ jest
+ .mocked(getComponentData)
+ .mockResolvedValueOnce({ component } as unknown as Awaited<ReturnType<typeof getComponentData>>)
+ .mockResolvedValueOnce({ component } as unknown as Awaited<
+ ReturnType<typeof getComponentData>
+ >);
+
+ jest
+ .mocked(getProjectAlmBinding)
+ .mockResolvedValueOnce(undefined as unknown as Awaited<ReturnType<typeof getProjectAlmBinding>>)
+ .mockResolvedValueOnce({
+ alm: AlmKeys.GitHub,
+ key: 'foo',
+ } as unknown as Awaited<ReturnType<typeof getProjectAlmBinding>>);
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
});
it('fetches status', async () => {
- (getComponentData as jest.Mock<any>).mockResolvedValueOnce({
+ jest.mocked(getComponentData).mockResolvedValueOnce({
component: {},
- });
+ } as unknown as Awaited<ReturnType<typeof getComponentData>>);
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
});
it('reload component after task progress finished', async () => {
- (getTasksForComponent as jest.Mock<any>)
+ jest
+ .mocked(getTasksForComponent)
.mockResolvedValueOnce({
queue: [{ id: 'foo', status: TaskStatuses.InProgress, type: TaskTypes.ViewRefresh }],
- })
+ } as unknown as Awaited<ReturnType<typeof getTasksForComponent>>)
.mockResolvedValueOnce({
queue: [],
- });
+ } as unknown as Awaited<ReturnType<typeof getTasksForComponent>>);
+
const wrapper = shallowRender();
// First round, there's something in the queue, and component navigation was
});
it('reloads component after task progress finished, and moves straight to current', async () => {
- (getComponentData as jest.Mock<any>).mockResolvedValueOnce({
+ jest.mocked(getComponentData).mockResolvedValueOnce({
component: { key: 'bar' },
- });
- (getTasksForComponent as jest.Mock<any>)
- .mockResolvedValueOnce({ queue: [] })
+ } as unknown as Awaited<ReturnType<typeof getComponentData>>);
+
+ jest
+ .mocked(getTasksForComponent)
+ .mockResolvedValueOnce({ queue: [] } as unknown as Awaited<
+ ReturnType<typeof getTasksForComponent>
+ >)
.mockResolvedValueOnce({
queue: [],
current: { id: 'foo', status: TaskStatuses.Success, type: TaskTypes.AppRefresh },
- });
+ } as unknown as Awaited<ReturnType<typeof getTasksForComponent>>);
+
const wrapper = shallowRender();
// First round, nothing in the queue, and component navigation was not called
});
it('only fully loads a non-empty component once', async () => {
- (getComponentData as jest.Mock<any>).mockResolvedValueOnce({
+ jest.mocked(getComponentData).mockResolvedValueOnce({
component: { key: 'bar', analysisDate: '2019-01-01' },
- });
- (getTasksForComponent as jest.Mock<any>).mockResolvedValueOnce({
+ } as unknown as Awaited<ReturnType<typeof getComponentData>>);
+
+ jest.mocked(getTasksForComponent).mockResolvedValueOnce({
queue: [],
current: { id: 'foo', status: TaskStatuses.Success, type: TaskTypes.Report },
- });
+ } as unknown as Awaited<ReturnType<typeof getTasksForComponent>>);
+
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
});
it('only fully reloads a non-empty component if there was previously some task in progress', async () => {
- (getComponentData as jest.Mock<any>).mockResolvedValueOnce({
+ jest.mocked(getComponentData).mockResolvedValueOnce({
component: { key: 'bar', analysisDate: '2019-01-01' },
- });
- (getTasksForComponent as jest.Mock<any>)
+ } as unknown as Awaited<ReturnType<typeof getComponentData>>);
+
+ jest
+ .mocked(getTasksForComponent)
.mockResolvedValueOnce({
queue: [{ id: 'foo', status: TaskStatuses.InProgress, type: TaskTypes.AppRefresh }],
- })
+ } as unknown as Awaited<ReturnType<typeof getTasksForComponent>>)
.mockResolvedValueOnce({
queue: [],
current: { id: 'foo', status: TaskStatuses.Success, type: TaskTypes.AppRefresh },
- });
+ } as unknown as Awaited<ReturnType<typeof getTasksForComponent>>);
+
const wrapper = shallowRender();
// First round, a pending task in the queue. This should trigger a reload of the
});
it('should show component not found if it does not exist', async () => {
- (getComponentNavigation as jest.Mock).mockRejectedValueOnce(
- new Response(null, { status: HttpStatus.NotFound })
- );
+ jest
+ .mocked(getComponentNavigation)
+ .mockRejectedValueOnce(new Response(null, { status: HttpStatus.NotFound }));
+
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
});
it('should redirect if the user has no access', async () => {
- (getComponentNavigation as jest.Mock).mockRejectedValueOnce(
- new Response(null, { status: HttpStatus.Forbidden })
- );
+ jest
+ .mocked(getComponentNavigation)
+ .mockRejectedValueOnce(new Response(null, { status: HttpStatus.Forbidden }));
+
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
expect(handleRequiredAuthorization).toHaveBeenCalled();
it('should redirect if the component is a portfolio', async () => {
const componentKey = 'comp-key';
- (getComponentData as jest.Mock<any>).mockResolvedValueOnce({
+
+ jest.mocked(getComponentData).mockResolvedValueOnce({
component: { key: componentKey, breadcrumbs: [{ qualifier: ComponentQualifier.Portfolio }] },
- });
+ } as unknown as Awaited<ReturnType<typeof getComponentData>>);
const replace = jest.fn();
location: mockLocation({ pathname: '/dashboard' }),
router: mockRouter({ replace }),
});
- await waitAndUpdate(wrapper);
- expect(replace).toHaveBeenCalledWith({ pathname: '/portfolio', search: `?id=${componentKey}` });
-});
-
-it('should display display the unavailable page if the component needs issue sync', async () => {
- (getComponentData as jest.Mock).mockResolvedValueOnce({
- component: { key: 'test', qualifier: ComponentQualifier.Project, needIssueSync: true },
- });
-
- const wrapper = shallowRender();
await waitAndUpdate(wrapper);
-
- expect(wrapper.find(PageUnavailableDueToIndexation).exists()).toBe(true);
+ expect(replace).toHaveBeenCalledWith({ pathname: '/portfolio', search: `?id=${componentKey}` });
});
describe('should correctly validate the project binding depending on the context', () => {
['has a project binding; check is OK', COMPONENT, undefined, 1],
['has a project binding; check is not OK', COMPONENT, PROJECT_BINDING_ERRORS, 1],
])('%s', async (_, component, projectBindingErrors = undefined, n = 0) => {
- (getComponentNavigation as jest.Mock).mockResolvedValueOnce({});
- (getComponentData as jest.Mock<any>).mockResolvedValueOnce({ component });
+ jest
+ .mocked(getComponentNavigation)
+ .mockResolvedValueOnce({} as unknown as Awaited<ReturnType<typeof getComponentNavigation>>);
+
+ jest
+ .mocked(getComponentData)
+ .mockResolvedValueOnce({ component } as unknown as Awaited<
+ ReturnType<typeof getComponentData>
+ >);
if (n > 0) {
- (validateProjectAlmBinding as jest.Mock).mockResolvedValueOnce(projectBindingErrors);
+ jest.mocked(validateProjectAlmBinding).mockResolvedValueOnce(projectBindingErrors);
}
const wrapper = shallowRender({ hasFeature: () => true });
const component = mockComponent({
breadcrumbs: [{ key: 'foo', name: 'Foo', qualifier: componentQualifier }],
});
- (getComponentNavigation as jest.Mock).mockResolvedValueOnce({});
- (getComponentData as jest.Mock<any>).mockResolvedValueOnce({ component });
+
+ jest
+ .mocked(getComponentNavigation)
+ .mockResolvedValueOnce({} as unknown as Awaited<ReturnType<typeof getComponentNavigation>>);
+
+ jest
+ .mocked(getComponentData)
+ .mockResolvedValueOnce({ component } as unknown as Awaited<
+ ReturnType<typeof getComponentData>
+ >);
const wrapper = shallowRender();
await waitAndUpdate(wrapper);