import React from 'react'; import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper'; import { Route } from 'react-router-dom'; import nock, { nockInstance, assertNockRequest, mockAutocomplete, mockSetting } 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 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'; const cvPromotePath = api.getApiUrl('/content_view_versions/10/promote'); 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'; let firstVersion; let searchDelayScope; let autoSearchScope; let envScope; beforeEach(() => { const { results } = cvVersionsData; [firstVersion] = results; searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0); autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing'); envScope = nockInstance .get(environmentPathsPath) .query(true) .reply(200, environmentPathsData); }); afterEach(() => { nock.cleanAll(); assertNockRequest(envScope); assertNockRequest(searchDelayScope); assertNockRequest(autoSearchScope); }); 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, done); }); test('Can link to view environment and see publish time', async () => { 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('dev')[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); }); test('Can show package and erratas and link to list page', async () => { 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/rpmPackages/'); 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); }); test('Can show additional content and link to list page', async () => { 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); }); test('Can load for empty versions', async () => { 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("You currently don't have any versions for this content view.")).toBeInTheDocument()); assertNockRequest(autocompleteScope); assertNockRequest(scope); }); 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) .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, 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 taskSuccessScope = nockInstance .get(taskPollingUrl) .reply(200, contentViewTaskResponseData); const reloadScope = nockInstance .get(cvVersions) .query(true) .reply(200, cvVersionsData); const { getByText, queryByLabelText, 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 now showing on the screen. await patientlyWaitFor(() => { expect(queryByText(`Version ${firstVersion.version}`)).toBeInTheDocument(); expect(getByLabelText('task_presenter')).toBeInTheDocument(); }); const { results } = cvVersionsData; [firstVersion] = results; // Assert that the CV version is shown and active task is not rendered anymore on the screen. await patientlyWaitFor(() => { expect(getByText(`Version ${firstVersion.version}`)).toBeInTheDocument(); expect(queryByLabelText('task_presenter')).not.toBeInTheDocument(); }); assertNockRequest(autocompleteScope); assertNockRequest(scope); assertNockRequest(taskSuccessScope); // Assert CV Versions API is called upon task completion assertNockRequest(reloadScope, done); }); test('Can open Promote Modal', async (done) => { const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl); const scope = nockInstance .get(cvVersions) .times(2) .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(); }); assertNockRequest(autocompleteScope); assertNockRequest(scope); assertNockRequest(promoteScope); // Page is refreshed assertNockRequest(scope, done); });