webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js
import React from 'react';
import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
import { nockInstance, assertNockRequest, mockAutocomplete } from '../../../../../test-utils/nockWrapper';
import api from '../../../../../services/api';
import CONTENT_VIEWS_KEY from '../../../ContentViewsConstants';
import ContentViewComponents from '../ContentViewComponents';
import cvComponentData from './contentViewComponents.fixtures.json';
import cvUnpublishedComponentData from './unpublishedCVComponents.fixtures.json';
import cvPublishedComponentData from './publishedContentViewDetails.fixtures.json';
import cvDetails from '../../__tests__/contentViewDetails.fixtures.json';
import compositeCvDetails from './compositeCVDetails.fixtures.json';
const renderOptions = { apiNamespace: `${CONTENT_VIEWS_KEY}_1` };
const cvComponentsWithoutSearch = api.getApiUrl('/content_views/4/content_view_components/show_all?per_page=20&page=1&status=All');
const cvComponents = api.getApiUrl('/content_views/4/content_view_components/show_all?per_page=20&page=1&search=&status=All');
const addComponentURL = api.getApiUrl('/content_views/4/content_view_components/add');
const publishedComponentDetailsURL = api.getApiUrl('/content_views/13');
const cvDetailsPath = api.getApiUrl('/content_views/4');
const removeComponentURL = api.getApiUrl('/content_views/4/content_view_components/remove');
const autocompleteUrl = '/content_views/auto_complete_search';
const autocompleteQuery = {
organization_id: 1,
search: '',
};
let firstComponent;
beforeEach(() => {
const { results } = cvComponentData;
[firstComponent] = results;
});
test('Can call API and show components on page load', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
const scope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const { getByText, queryByText } = renderWithRedux(
<ContentViewComponents cvId={4} details={cvDetails} />,
renderOptions,
);
// Nothing will show at first, page is loading
expect(queryByText(firstComponent.content_view.label)).toBeNull();
// Assert that the repo name is now showing on the screen, but wait for it to appear.
await patientlyWaitFor(() => expect(getByText(firstComponent.content_view.label))
.toBeInTheDocument());
assertNockRequest(autocompleteScope);
assertNockRequest(scope, done);
});
test('Can call API and show unpublished components', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
const scope = nockInstance
.get(cvComponents)
.reply(200, cvUnpublishedComponentData);
const unpublishedComponent = cvUnpublishedComponentData.results[1];
const { getByText, queryByText, getAllByText } = renderWithRedux(
<ContentViewComponents cvId={4} details={cvDetails} />,
renderOptions,
);
// Nothing will show at first, page is loading
expect(queryByText(unpublishedComponent.content_view.label)).toBeNull();
// Assert that the repo name is now showing on the screen, but wait for it to appear.
await patientlyWaitFor(() => {
expect(getByText(unpublishedComponent.content_view.label)).toBeTruthy();
expect(getAllByText('Not yet published')).toHaveLength(4);
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope, done);
});
test('Can link to view environment', async () => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
const scope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const { getAllByText } = renderWithRedux(
<ContentViewComponents cvId={4} details={cvDetails} />,
renderOptions,
);
await patientlyWaitFor(() => {
expect(getAllByText('Library')[0].closest('a'))
.toHaveAttribute('href', '/lifecycle_environments/1');
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
});
test('Can search for component content views in composite view', async (done) => {
const lastComponent = cvComponentData.results[1];
const { name: firstComponentName } = firstComponent.content_view;
const { name: lastComponentName } = lastComponent.content_view;
const searchQueryMatcher = {
organization_id: 1,
search: `name = ${lastComponentName}`,
};
const searchResults = [
{
completed: `name = ${lastComponentName}`,
part: 'and',
label: `name = ${lastComponentName} and`,
category: 'Operators',
},
{
completed: `name = ${lastComponentName}`,
part: 'or',
label: `name = ${lastComponentName} or`,
category: 'Operators',
},
];
const cvComponentsScope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
const withSearchScope = mockAutocomplete(
nockInstance,
autocompleteUrl,
searchQueryMatcher,
searchResults,
);
const { getByText, queryByText, getByLabelText } =
renderWithRedux(<ContentViewComponents cvId={4} details={cvDetails} />, renderOptions);
// Basic results showing
await patientlyWaitFor(() => {
expect(getByText(firstComponentName)).toBeInTheDocument();
expect(getByText(lastComponentName)).toBeInTheDocument();
});
// Search and only searched result shows
const searchInput = getByLabelText('Search input');
expect(searchInput).toBeInTheDocument();
searchInput.focus();
fireEvent.change(searchInput, { target: { value: `name = ${lastComponentName}` } });
await patientlyWaitFor(() => {
expect(getByText(`name = ${lastComponentName} and`)).toBeInTheDocument();
expect(queryByText(`name = ${firstComponentName} and`)).not.toBeInTheDocument();
});
assertNockRequest(autocompleteScope);
assertNockRequest(cvComponentsScope);
assertNockRequest(withSearchScope, done);
});
test('Can handle no components being present', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
const noResults = {
total: 0,
subtotal: 0,
page: 1,
per_page: 20,
results: [],
};
const scope = nockInstance
.get(cvComponents)
.reply(200, noResults);
const mockDetails = {
label: 'test_empty',
permissions: {
view_content_views: true,
edit_content_views: true,
destroy_content_views: true,
publish_content_views: true,
promote_or_remove_content_views: true,
},
};
const { queryByText } =
renderWithRedux(<ContentViewComponents cvId={4} details={mockDetails} />, renderOptions);
expect(queryByText(firstComponent.content_view.label)).toBeNull();
await patientlyWaitFor(() => expect(queryByText('No content views to add yet')).toBeInTheDocument());
assertNockRequest(autocompleteScope);
assertNockRequest(scope, done);
});
test('Can add published component views to content view with modal', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
const scope = nockInstance
.get(cvComponentsWithoutSearch)
.reply(200, cvComponentData);
const returnScope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const publishedComponentVersionsScope = nockInstance
.get(publishedComponentDetailsURL)
.query(true)
.reply(200, cvPublishedComponentData);
const addComponentParams = {
compositeContentViewId: 4,
components: [{ content_view_version_id: 13 }],
};
const addComponentScope = nockInstance
.put(addComponentURL, addComponentParams)
.reply(200, {});
const cvDetailsScope = nockInstance
.get(cvDetailsPath)
.query(true)
.reply(200, compositeCvDetails);
const {
getByText, getByLabelText, queryByLabelText, getAllByLabelText,
} = renderWithRedux(
<ContentViewComponents cvId={4} details={cvDetails} />,
renderOptions,
);
await patientlyWaitFor(() => {
expect(getAllByLabelText('Actions')[2]).toHaveAttribute('aria-expanded', 'false');
});
fireEvent.click(getAllByLabelText('Actions')[2]);
expect(getAllByLabelText('Actions')[2]).toHaveAttribute('aria-expanded', 'true');
await patientlyWaitFor(() => {
expect(getByText('Add')).toBeInTheDocument();
});
fireEvent.click(getByText('Add'));
await patientlyWaitFor(() => {
expect(getByText('Add content view')).toBeInTheDocument();
});
fireEvent.click(getByLabelText('add_component'));
await patientlyWaitFor(() => {
expect(queryByLabelText('add_component')).not.toBeInTheDocument();
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
assertNockRequest(publishedComponentVersionsScope);
assertNockRequest(addComponentScope);
assertNockRequest(returnScope);
assertNockRequest(cvDetailsScope, done);
});
test('Can add unpublished component views to content view', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
const scope = nockInstance
.get(cvComponentsWithoutSearch)
.reply(200, cvComponentData);
const returnScope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const addComponentParams = {
compositeContentViewId: 4,
components: [{ latest: true, content_view_id: 9 }],
};
const addComponentScope = nockInstance
.put(addComponentURL, addComponentParams)
.reply(200, {});
const cvDetailsScope = nockInstance
.get(cvDetailsPath)
.query(true)
.reply(200, compositeCvDetails);
const { getByText, getAllByLabelText } = renderWithRedux(
<ContentViewComponents cvId={4} details={cvDetails} />,
renderOptions,
);
await patientlyWaitFor(() => {
expect(getAllByLabelText('Actions').slice(-1)[0]).toHaveAttribute('aria-expanded', 'false');
});
fireEvent.click(getAllByLabelText('Actions').slice(-1)[0]);
expect(getAllByLabelText('Actions').slice(-1)[0]).toHaveAttribute('aria-expanded', 'true');
await patientlyWaitFor(() => expect(getByText('Add')).toBeInTheDocument());
fireEvent.click(getByText('Add'));
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
assertNockRequest(addComponentScope);
assertNockRequest(returnScope);
assertNockRequest(cvDetailsScope, done);
});
test('Can remove component views from content view', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
const scope = nockInstance
.get(cvComponentsWithoutSearch)
.reply(200, cvComponentData);
const returnScope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const removeComponentParams = {
compositeContentViewId: 4,
component_ids: [28],
};
const removeComponentScope = nockInstance
.put(removeComponentURL, removeComponentParams)
.reply(200, {});
const cvDetailsScope = nockInstance
.get(cvDetailsPath)
.query(true)
.reply(200, compositeCvDetails);
const { getByText, getAllByLabelText } = renderWithRedux(
<ContentViewComponents cvId={4} details={cvDetails} />,
renderOptions,
);
await patientlyWaitFor(() => {
expect(getAllByLabelText('Actions')[0]).toHaveAttribute('aria-expanded', 'false');
});
fireEvent.click(getAllByLabelText('Actions')[0]);
expect(getAllByLabelText('Actions')[0]).toHaveAttribute('aria-expanded', 'true');
await patientlyWaitFor(() => expect(getByText('Remove')).toBeInTheDocument());
fireEvent.click(getByText('Remove'));
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
assertNockRequest(removeComponentScope);
assertNockRequest(returnScope);
assertNockRequest(cvDetailsScope, done);
});
test('Can bulk add component views to content view with modal', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl, autocompleteQuery);
const scope = nockInstance
.get(cvComponentsWithoutSearch)
.reply(200, cvComponentData);
const returnScope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const addComponentParams = {
compositeContentViewId: 4,
components: [{ content_view_version_id: 42 }, { latest: true, content_view_id: 9 }],
};
const addComponentScope = nockInstance
.put(addComponentURL, addComponentParams)
.reply(200, {});
const cvDetailsScope = nockInstance
.get(cvDetailsPath)
.query(true)
.reply(200, compositeCvDetails);
const {
getAllByText, getByLabelText, queryByText, getAllByRole,
} = renderWithRedux(
<ContentViewComponents cvId={4} details={cvDetails} />,
renderOptions,
);
await patientlyWaitFor(() => {
expect(getByLabelText('Select row 2')).toBeInTheDocument();
expect(getByLabelText('bulk_add_components')).toHaveAttribute('aria-disabled', 'true');
});
fireEvent.click(getByLabelText('Select row 2'));
fireEvent.click(getByLabelText('Select row 3'));
await patientlyWaitFor(() => {
expect(getByLabelText('bulk_add_components')).toHaveAttribute('aria-disabled', 'false');
});
fireEvent.click(getByLabelText('bulk_add_components'));
await patientlyWaitFor(() => {
expect(getAllByText('Add content views')[1]).toBeInTheDocument();
expect(getAllByRole('textbox')[0]).toHaveValue('Version 4.0 (3 days ago)');
});
fireEvent.click(getAllByRole('textbox')[0]);
fireEvent.click(queryByText('Version 3.0'));
fireEvent.click(getByLabelText('add_components'));
await patientlyWaitFor(() => {
expect(queryByText('Select available version of content views to use')).not.toBeInTheDocument();
expect(getByLabelText('bulk_add_components')).toHaveAttribute('aria-disabled', 'false');
});
assertNockRequest(autocompleteScope);
assertNockRequest(scope);
assertNockRequest(addComponentScope);
assertNockRequest(returnScope);
assertNockRequest(cvDetailsScope, done);
});