import React from 'react';
import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
import { nockInstance, assertNockRequest, mockAutocomplete, mockSetting } 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';
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 removeComponentURL = api.getApiUrl('/content_views/4/content_view_components/remove');
const cvComponentsSearchURL = api.getApiUrl('/content_views/4/content_view_components/show_all?per_page=20&page=1&search=name+%3D+%227%22&status=All');
const autocompleteUrl = '/content_views/auto_complete_search';
let firstComponent;
let searchDelayScope;
let autoSearchScope;
beforeEach(() => {
const { results } = cvComponentData;
[firstComponent] = results;
searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
});
afterEach(() => {
assertNockRequest(searchDelayScope);
assertNockRequest(autoSearchScope);
});
test('Can call API and show components on page load', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const scope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const { getByText, queryByText } = renderWithRedux(
,
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);
const scope = nockInstance
.get(cvComponents)
.reply(200, cvUnpublishedComponentData);
const unpublishedComponent = cvUnpublishedComponentData.results[1];
const { getByText, queryByText, getAllByText } = renderWithRedux(
,
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);
const scope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const { getAllByText } = renderWithRedux(
,
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 = actualParams => actualParams?.search?.includes(lastComponentName);
const cvComponentsScope = nockInstance
.get(cvComponents)
.reply(200, cvComponentData);
const cvComponentsSearchScope = nockInstance
.get(cvComponentsSearchURL)
.reply(200, { results: [lastComponent] });
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
const withSearchScope = mockAutocomplete(nockInstance, autocompleteUrl, searchQueryMatcher);
const { getByText, queryByText, getByLabelText } =
renderWithRedux(, renderOptions);
// Basic results showing
await patientlyWaitFor(() => {
expect(getByText(firstComponentName)).toBeInTheDocument();
expect(getByText(lastComponentName)).toBeInTheDocument();
});
// Search and only searched result shows
const searchInput = getByLabelText(/text input for search/i);
expect(searchInput).toBeInTheDocument();
fireEvent.change(searchInput, { target: { value: `name = "${lastComponentName}"` } });
await patientlyWaitFor(() => {
expect(getByText(lastComponentName)).toBeInTheDocument();
expect(queryByText(firstComponentName)).not.toBeInTheDocument();
});
assertNockRequest(autocompleteScope);
assertNockRequest(cvComponentsScope);
assertNockRequest(withSearchScope);
assertNockRequest(cvComponentsSearchScope, done);
});
test('Can handle no components being present', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
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(, renderOptions);
expect(queryByText(firstComponent.content_view.label)).toBeNull();
await patientlyWaitFor(() => expect(queryByText('No content views belong to test_empty')).toBeInTheDocument());
assertNockRequest(autocompleteScope);
assertNockRequest(scope, done);
});
test('Can add published component views to content view with modal', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
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: 85 }],
};
const addComponentScope = nockInstance
.put(addComponentURL, addComponentParams)
.reply(200, {});
const {
getByText, getByLabelText, queryByLabelText, getAllByLabelText,
} = renderWithRedux(
,
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, done);
});
test('Can add unpublished component views to content view', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
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 { getByText, getAllByLabelText } = renderWithRedux(
,
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, done);
});
test('Can remove component views from content view', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
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 { getByText, getAllByLabelText } = renderWithRedux(
,
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, done);
});
test('Can bulk add component views to content view with modal', async (done) => {
const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
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: 44 }, { latest: true, content_view_id: 9 }],
};
const addComponentScope = nockInstance
.put(addComponentURL, addComponentParams)
.reply(200, {});
const {
getAllByText, getByLabelText, queryByText,
} = renderWithRedux(
,
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();
});
fireEvent.click(getByLabelText('version-select-cv-10'));
fireEvent.click(getByLabelText('cv-10-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, done);
});