import React from 'react';
import { act, renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
import { Route } from 'react-router-dom';
import { nockInstance, assertNockRequest, mockAutocomplete } from '../../../../../test-utils/nockWrapper';
import api from '../../../../../services/api';
import CONTENT_VIEWS_KEY from '../../../ContentViewsConstants';
import ContentViewVersions from '../ContentViewVersions';
import cvVersionsData from './contentViewVersions.fixtures.json';
import cvVersionsOutOfEnvData from './contentViewVersionsLatestEnvironment.fixtures.json';
import emptyCVVersionData from './emptyCVVersion.fixtures.json';
import cvVersionsTasksData from './contentViewVersionsWithTask.fixtures.json';
import contentViewTaskInProgressResponseData from './contentViewTaskInProgressResponse.fixtures.json';
import contentViewTaskResponseData from './contentViewTaskResponse.fixtures.json';
import cvDetailData from '../../../../ContentViews/__tests__/mockDetails.fixtures.json';
import environmentPathsData from '../../../Publish/__tests__/environmentPaths.fixtures.json';
import cvIndexData from '../../../__tests__/contentViewList.fixtures.json';
import contentViewFilterData from '../../Filters/__tests__/contentViewFilters.fixtures.json';
const cvPromotePath = api.getApiUrl('/content_view_versions/10/promote');
const cvPromotePath2 = api.getApiUrl('/content_view_versions/11/promote');
const cvIndexPath = api.getApiUrl('/content_views');
const promoteResponseData = contentViewTaskInProgressResponseData;
const environmentPathsPath = api.getApiUrl('/organizations/1/environments/paths');
const withCVRoute = component => {component};
const renderOptions = {
apiNamespace: `${CONTENT_VIEWS_KEY}_VERSIONS_5`,
routerParams: {
initialEntries: [{ pathname: '/content_views/5' }],
initialIndex: 1,
},
};
const cvVersions = api.getApiUrl('/content_view_versions');
const autocompleteUrl = '/content_view_versions/auto_complete_search';
const taskPollingUrl = '/foreman_tasks/api/tasks/6b900ff8-62bb-42ac-8c45-da86b7258520';
const cvFiltersPath = api.getApiUrl('/content_view_filters?content_view_id=5');
let firstVersion;
let envScope;
beforeEach(() => {
const { results } = cvVersionsData;
[firstVersion] = results;
envScope = nockInstance
.get(environmentPathsPath)
.query(true)
.reply(200, environmentPathsData);
});
afterEach(() => {
assertNockRequest(envScope);
});
test('Can call API and show versions on page load', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, cvVersionsData);
const { getByText, queryByText } = renderWithRedux(
withCVRoute(),
renderOptions,
);
// Nothing will show at first, page is loading
expect(queryByText(`Version ${firstVersion.version}`)).toBeNull();
// Assert that the CV version is now showing on the screen, but wait for it to appear.
await patientlyWaitFor(() => {
expect(getByText(`Version ${firstVersion.version}`)).toBeTruthy();
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
act(done);
});
test('Can link to view environment and see publish time', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, cvVersionsData);
const { getByText, getAllByText } = renderWithRedux(
withCVRoute(),
renderOptions,
);
await patientlyWaitFor(() => {
// Able to display multiple env of version with humanized published/promoted date
expect(getAllByText('Library')[0].closest('a'))
.toHaveAttribute('href', '/lifecycle_environments/1');
expect(getByText('5 days ago')).toBeTruthy();
expect(getAllByText('dev1')[0].closest('a'))
.toHaveAttribute('href', '/lifecycle_environments/2');
expect(getAllByText('4 days ago')[0]).toBeTruthy();
// Able to display empty text for version in no environments
expect(getAllByText('No environments')).toHaveLength(3);
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
act(done);
});
test('Can show package and erratas and link to list page', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, cvVersionsData);
const { getByText, getAllByText } = renderWithRedux(
withCVRoute(),
renderOptions,
);
await patientlyWaitFor(() => {
expect(getAllByText(8)[0].closest('a'))
.toHaveAttribute('href', '/content_views/5#/versions/11/packages/');
expect(getAllByText(15)[0].closest('a'))
.toHaveAttribute('href', '/content_views/5#/versions/11/errata/');
expect(getByText(5)).toBeInTheDocument();
expect(getByText(3)).toBeInTheDocument();
expect(getByText(7)).toBeInTheDocument();
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
act(done);
});
test('Can show additional content and link to list page', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, cvVersionsData);
const { getByText } = renderWithRedux(
withCVRoute(),
renderOptions,
);
await patientlyWaitFor(() => {
expect(getByText('3 Files').closest('a'))
.toHaveAttribute('href', '/content_views/5#/versions/11/files/');
expect(getByText('1 Deb packages').closest('a'))
.toHaveAttribute('href', '/versions/11/debPackages');
expect(getByText('80 Python packages')).toBeInTheDocument();
expect(getByText('2 OSTree refs')).toBeInTheDocument();
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
act(done);
});
test('Can load for empty versions', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, emptyCVVersionData);
const { queryByText } = renderWithRedux(
withCVRoute(),
renderOptions,
);
expect(queryByText(`Version ${firstVersion.version}`)).toBeNull();
await patientlyWaitFor(() =>
expect(queryByText('No versions yet')).toBeInTheDocument());
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
act(done);
});
test('Can call API and show versions with tasks on page load', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const { results: withTaskResults } = cvVersionsTasksData;
[firstVersion] = withTaskResults;
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, cvVersionsTasksData);
const taskInProgressScope = nockInstance
.get(taskPollingUrl)
.times(4)
.reply(200, contentViewTaskInProgressResponseData);
const {
getByLabelText, queryByText,
} = renderWithRedux(
withCVRoute(),
renderOptions,
);
// Nothing will show at first, page is loading
expect(queryByText(`Version ${firstVersion.version}`)).toBeNull();
// Assert that the CV version and active task is rendered on the screen.
await patientlyWaitFor(() => {
expect(queryByText(`Version ${firstVersion.version}`)).toBeInTheDocument();
expect(getByLabelText('task_presenter')).toBeInTheDocument();
expect(getByLabelText('task_presenter')).toHaveAttribute('aria-valuenow', '50');
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
assertNockRequest(taskInProgressScope);
act(done);// Force the test to stop listening for tasks
});
test('Can open Promote Modal', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const cvScope = nockInstance
.get(cvIndexPath)
.query(true)
.reply(200, cvIndexData);
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, cvVersionsData);
const cvPromoteParams = {
id: 10, versionEnvironments: [], description: '', environment_ids: [5], force: true,
};
const promoteScope = nockInstance
.post(cvPromotePath, cvPromoteParams)
.reply(202, promoteResponseData);
const {
getByText, queryByText, getByLabelText, getAllByLabelText,
} = renderWithRedux(
withCVRoute(),
renderOptions,
);
expect(queryByText(`Version ${firstVersion.version}`)).toBeNull();
await patientlyWaitFor(() => {
expect(getByText(`Version ${firstVersion.version}`)).toBeInTheDocument();
});
// Expand Row Action
expect(getAllByLabelText('Actions')[1]).toHaveAttribute('aria-expanded', 'false');
fireEvent.click(getAllByLabelText('Actions')[1]);
expect(getAllByLabelText('Actions')[1]).toHaveAttribute('aria-expanded', 'true');
fireEvent.click(getByText('Promote'));
await patientlyWaitFor(() => {
expect(getByText('Select a lifecycle environment from the available promotion paths to promote new version.')).toBeInTheDocument();
expect(getByLabelText('prod')).toBeInTheDocument();
});
// Select env prod
fireEvent.click(getByLabelText('prod'));
fireEvent.click(getByLabelText('promote_content_view'));
// Modal closes itself
await patientlyWaitFor(() => {
expect(queryByText('Select a lifecycle environment from the available promotion paths to promote new version.')).toBeNull();
expect(getByText(`Version ${firstVersion.version}`)).toBeInTheDocument();
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
assertNockRequest(promoteScope);
// Page is refreshed
assertNockRequest(scope);
assertNockRequest(cvScope);
act(done);
});
test('Can open Promote Modal and show out of path warnings', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const cvScope = nockInstance
.get(cvIndexPath)
.query(true)
.reply(200, cvIndexData);
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, cvVersionsOutOfEnvData);
const cvPromoteParams = {
id: 11,
versionEnvironments: [
{
id: 1,
name: 'Library',
label: 'Library',
publish_date: '5 days',
permissions: {
readable: true,
promotable_or_removable: true,
all_hosts_editable: true,
all_keys_editable: true,
},
host_count: 0,
activation_key_count: 0,
},
{
id: 3,
name: 'test',
label: 'test',
publish_date: '4 days',
permissions: {
readable: true,
promotable_or_removable: true,
all_hosts_editable: true,
all_keys_editable: true,
},
host_count: 0,
activation_key_count: 0,
},
],
description: '',
environment_ids: [5, 4],
force: true,
};
const promoteScope = nockInstance
.post(cvPromotePath2, cvPromoteParams)
.reply(202, promoteResponseData);
const {
getByText, queryByText, getByLabelText, getAllByLabelText,
} = renderWithRedux(
withCVRoute(),
renderOptions,
);
expect(queryByText(`Version ${firstVersion.version}`)).toBeNull();
await patientlyWaitFor(() => {
expect(getByText(`Version ${firstVersion.version}`)).toBeInTheDocument();
});
// Expand Row Action
expect(getAllByLabelText('Actions')[0]).toHaveAttribute('aria-expanded', 'false');
fireEvent.click(getAllByLabelText('Actions')[0]);
expect(getAllByLabelText('Actions')[0]).toHaveAttribute('aria-expanded', 'true');
fireEvent.click(getByText('Promote'));
await patientlyWaitFor(() => {
expect(getByText('Select a lifecycle environment from the available promotion paths to promote new version.')).toBeInTheDocument();
expect(getByLabelText('prod')).toBeInTheDocument();
});
// Select env prod out of Env path: Library, dev1, test, test2, prod
fireEvent.click(getByLabelText('prod'));
await patientlyWaitFor(() => {
// Force promotion info is shown because test -> prod is out of order
expect(getByText('Force promotion')).toBeInTheDocument();
});
fireEvent.click(getByLabelText('test2'));
await patientlyWaitFor(() => {
// Force promotion info is shown because test -> test2 -> prod is out of order
expect(queryByText('Force promotion')).toBeNull();
});
fireEvent.click(getByLabelText('promote_content_view'));
// Modal closes itself
await patientlyWaitFor(() => {
expect(queryByText('Select a lifecycle environment from the available promotion paths to promote new version.')).toBeNull();
expect(getByText(`Version ${firstVersion.version}`)).toBeInTheDocument();
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
assertNockRequest(promoteScope);
// Page is refreshed
assertNockRequest(scope);
assertNockRequest(cvScope);
act(done);
});
test('Can reload versions upon task completion', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const { results: withTaskResults } = cvVersionsTasksData;
[firstVersion] = withTaskResults;
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, cvVersionsTasksData);
const cvScope = nockInstance
.get(cvIndexPath)
.query(true)
.reply(200, cvIndexData);
const taskSuccessScope = nockInstance
.get(taskPollingUrl)
.times(6)
.reply(200, contentViewTaskResponseData);
const reloadScope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, cvVersionsData);
const {
queryByLabelText, queryByText,
} = renderWithRedux(
withCVRoute(),
renderOptions,
);
// Nothing will show at first, page is loading
expect(queryByText(`Version ${firstVersion.version}`)).toBeNull();
// Assert that the CV version is shown and active task is not rendered anymore on the screen.
await patientlyWaitFor(() => {
expect(queryByLabelText('task_presenter')).not.toBeInTheDocument();
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
assertNockRequest(taskSuccessScope);
// Assert CV Versions API is called upon task completion
assertNockRequest(reloadScope);
assertNockRequest(cvScope);
act(done);
});
test('Shows call-to-action when there are no versions', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, emptyCVVersionData);
const scopeWizard = nockInstance
.get(environmentPathsPath)
.query(true)
.reply(200, environmentPathsData);
const filterScope = nockInstance
.get(cvFiltersPath)
.reply(200, contentViewFilterData);
const { getByText, queryByText } = renderWithRedux(
withCVRoute(),
renderOptions,
);
// Nothing will show at first, page is loading
expect(queryByText('Publish new version')).toBeNull();
// Assert that the CV version is now showing on the screen, but wait for it to appear.
await patientlyWaitFor(() => {
expect(getByText('Publish new version')).toBeInTheDocument();
});
fireEvent.click(getByText('Publish new version'));
await patientlyWaitFor(() => expect(getByText('Publish new version - 1.0')).toBeInTheDocument);
assertNockRequest(scopeWizard);
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
assertNockRequest(filterScope);
act(done);
});
test('Hides selectAllCheckbox when there are no versions', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const scope = nockInstance
.get(cvVersions)
.query(true)
.reply(200, emptyCVVersionData);
const { queryByLabelText, queryByText, getByText } = renderWithRedux(
withCVRoute(),
renderOptions,
);
// Nothing will show at first, page is loading
expect(queryByText('Publish new version')).toBeNull();
// Assert that the CV version is now showing on the screen, but wait for it to appear.
await patientlyWaitFor(() => {
expect(getByText('Publish new version')).toBeInTheDocument();
expect(queryByLabelText('Select all')).not.toBeInTheDocument();
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
act(done);
});