The user should not be able to continue without selecting an upload destination. The uploadDestination fields are now checked to see if one is selected before enabling the Next button in the footer. Also, the onSaveInProgress variable is changed to isSaveInProgress to conform with the other validation variables.
567 lines
18 KiB
JavaScript
567 lines
18 KiB
JavaScript
import '@testing-library/jest-dom';
|
|
|
|
import React from 'react';
|
|
import { screen, getByText, waitFor, waitForElementToBeRemoved, within } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { renderWithReduxRouter } from '../../testUtils';
|
|
import CreateImageWizard from '../../../SmartComponents/CreateImageWizard/CreateImageWizard';
|
|
import api from '../../../api.js';
|
|
|
|
let historySpy = undefined;
|
|
|
|
function verifyButtons() {
|
|
// these buttons exist everywhere
|
|
const next = screen.getByRole('button', { name: /Next/ });
|
|
const back = screen.getByRole('button', { name: /Back/ });
|
|
const cancel = screen.getByRole('button', { name: /Cancel/ });
|
|
|
|
return [ next, back, cancel ];
|
|
}
|
|
|
|
function verifyCancelButton(cancel, history) {
|
|
cancel.click();
|
|
|
|
// this goes back to the landing page
|
|
// but jsdom will not render the new page so we can't assert on that
|
|
expect(history).toHaveBeenCalledTimes(1);
|
|
expect(history).toHaveBeenCalledWith('/landing');
|
|
}
|
|
|
|
// mock the insights dependency
|
|
beforeAll(() => {
|
|
global.insights = {
|
|
chrome: {
|
|
auth: {
|
|
getUser: () => {
|
|
return {
|
|
identity: {
|
|
internal: {
|
|
org_id: 5
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
};
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
historySpy = undefined;
|
|
});
|
|
|
|
// restore global mock
|
|
afterAll(() => {
|
|
global.insights = undefined;
|
|
});
|
|
|
|
describe('Create Image Wizard', () => {
|
|
beforeEach(() => {
|
|
renderWithReduxRouter(<CreateImageWizard />);
|
|
});
|
|
|
|
test('renders component', () => {
|
|
// check heading
|
|
screen.getByRole('heading', { name: /Create image/ });
|
|
|
|
// left sidebar navigation
|
|
const sidebar = screen.getByRole('navigation');
|
|
|
|
getByText(sidebar, 'Image output');
|
|
getByText(sidebar, 'Registration');
|
|
getByText(sidebar, 'Review');
|
|
});
|
|
});
|
|
|
|
describe('Step Image output', () => {
|
|
beforeEach(() => {
|
|
const { _component, history } = renderWithReduxRouter(<CreateImageWizard />);
|
|
historySpy = jest.spyOn(history, 'push');
|
|
|
|
// left sidebar navigation
|
|
const sidebar = screen.getByRole('navigation');
|
|
const anchor = getByText(sidebar, 'Image output');
|
|
|
|
// select aws as upload destination
|
|
const awsTile = screen.getByTestId('upload-aws');
|
|
awsTile.click();
|
|
// load from sidebar
|
|
anchor.click();
|
|
});
|
|
|
|
test('clicking Next loads Upload to AWS', () => {
|
|
const [ next, , ] = verifyButtons();
|
|
next.click();
|
|
|
|
screen.getByText('AWS account ID');
|
|
});
|
|
|
|
test('Back button is disabled', () => {
|
|
const [ , back, ] = verifyButtons();
|
|
|
|
// note: there is no `disabled` attribute and
|
|
// .toBeDissabled() fails
|
|
expect(back).toHaveClass('pf-m-disabled');
|
|
});
|
|
|
|
test('clicking Cancel loads landing page', () => {
|
|
const [ , , cancel ] = verifyButtons();
|
|
verifyCancelButton(cancel, historySpy);
|
|
});
|
|
|
|
test('allows chosing a release', () => {
|
|
const release = screen.getByTestId('release-select');
|
|
expect(release).toBeEnabled();
|
|
|
|
userEvent.selectOptions(release, [ 'rhel-8' ]);
|
|
});
|
|
|
|
test('target environment is required', () => {
|
|
const destination = screen.getByTestId('target-select');
|
|
const required = within(destination).getByText('*');
|
|
expect(destination).toBeEnabled();
|
|
expect(destination).toContainElement(required);
|
|
});
|
|
});
|
|
|
|
describe('Step Upload to AWS', () => {
|
|
beforeEach(() => {
|
|
const { _component, history } = renderWithReduxRouter(<CreateImageWizard />);
|
|
historySpy = jest.spyOn(history, 'push');
|
|
|
|
// select aws as upload destination
|
|
const awsTile = screen.getByTestId('upload-aws');
|
|
awsTile.click();
|
|
|
|
// left sidebar navigation
|
|
const sidebar = screen.getByRole('navigation');
|
|
const anchor = getByText(sidebar, 'Amazon Web Services');
|
|
|
|
// load from sidebar
|
|
anchor.click();
|
|
});
|
|
|
|
test('clicking Next loads Registration', () => {
|
|
const [ next, , ] = verifyButtons();
|
|
next.click();
|
|
|
|
screen.getByText('Register the system');
|
|
});
|
|
|
|
test('clicking Back loads Release', () => {
|
|
const [ , back, ] = verifyButtons();
|
|
back.click();
|
|
|
|
screen.getByTestId('release-select');
|
|
});
|
|
|
|
test('clicking Cancel loads landing page', () => {
|
|
const [ , , cancel ] = verifyButtons();
|
|
verifyCancelButton(cancel, historySpy);
|
|
});
|
|
|
|
test('the aws account id fieldis shown and required', () => {
|
|
const accessKeyId = screen.getByTestId('aws-account-id');
|
|
expect(accessKeyId).toHaveValue('');
|
|
expect(accessKeyId).toBeEnabled();
|
|
expect(accessKeyId).toBeRequired();
|
|
});
|
|
});
|
|
|
|
describe('Step Upload to Google', () => {
|
|
beforeEach(() => {
|
|
const { _component, history } = renderWithReduxRouter(<CreateImageWizard />);
|
|
historySpy = jest.spyOn(history, 'push');
|
|
|
|
// select aws as upload destination
|
|
const awsTile = screen.getByTestId('upload-google');
|
|
awsTile.click();
|
|
|
|
// left sidebar navigation
|
|
const sidebar = screen.getByRole('navigation');
|
|
const anchor = getByText(sidebar, 'Google Cloud Platform');
|
|
|
|
// load from sidebar
|
|
anchor.click();
|
|
});
|
|
|
|
test('clicking Next loads Registration', () => {
|
|
const [ next, , ] = verifyButtons();
|
|
next.click();
|
|
|
|
screen.getByText('Register the system');
|
|
});
|
|
|
|
test('clicking Back loads Release', () => {
|
|
const [ , back, ] = verifyButtons();
|
|
back.click();
|
|
|
|
screen.getByTestId('release-select');
|
|
});
|
|
|
|
test('clicking Cancel loads landing page', () => {
|
|
const [ , , cancel ] = verifyButtons();
|
|
verifyCancelButton(cancel, historySpy);
|
|
});
|
|
|
|
test('the google account id field is shown and required', () => {
|
|
const accessKeyId = screen.getByTestId('input-google-user');
|
|
expect(accessKeyId).toHaveValue('');
|
|
expect(accessKeyId).toBeEnabled();
|
|
expect(accessKeyId).toBeRequired();
|
|
});
|
|
});
|
|
|
|
describe('Step Upload to Azure', () => {
|
|
beforeEach(() => {
|
|
const { _component, history } = renderWithReduxRouter(<CreateImageWizard />);
|
|
historySpy = jest.spyOn(history, 'push');
|
|
|
|
// select aws as upload destination
|
|
const azureTile = screen.getByTestId('upload-azure');
|
|
azureTile.click();
|
|
|
|
// left sidebar navigation
|
|
const sidebar = screen.getByRole('navigation');
|
|
const anchor = getByText(sidebar, 'Microsoft Azure');
|
|
|
|
// load from sidebar
|
|
anchor.click();
|
|
});
|
|
|
|
test('clicking Next loads Registration', () => {
|
|
const [ next, , ] = verifyButtons();
|
|
next.click();
|
|
|
|
screen.getByText('Register the system');
|
|
});
|
|
|
|
test('clicking Back loads Release', () => {
|
|
const [ , back, ] = verifyButtons();
|
|
back.click();
|
|
|
|
screen.getByTestId('release-select');
|
|
});
|
|
|
|
test('clicking Cancel loads landing page', () => {
|
|
const [ , , cancel ] = verifyButtons();
|
|
verifyCancelButton(cancel, historySpy);
|
|
});
|
|
|
|
test('the azure upload fields are shown and required', () => {
|
|
const tenantId = screen.getByTestId('azure-tenant-id');
|
|
expect(tenantId).toHaveValue('');
|
|
expect(tenantId).toBeEnabled();
|
|
expect(tenantId).toBeRequired();
|
|
|
|
const subscription = screen.getByTestId('azure-subscription-id');
|
|
expect(subscription).toHaveValue('');
|
|
expect(subscription).toBeEnabled();
|
|
expect(subscription).toBeRequired();
|
|
|
|
const resourceGroup = screen.getByTestId('azure-resource-group');
|
|
expect(resourceGroup).toHaveValue('');
|
|
expect(resourceGroup).toBeEnabled();
|
|
expect(resourceGroup).toBeRequired();
|
|
});
|
|
});
|
|
|
|
describe('Step Registration', () => {
|
|
beforeEach(() => {
|
|
const { _component, history } = renderWithReduxRouter(<CreateImageWizard />);
|
|
historySpy = jest.spyOn(history, 'push');
|
|
|
|
// select aws as upload destination
|
|
const awsTile = screen.getByTestId('upload-aws');
|
|
awsTile.click();
|
|
|
|
// left sidebar navigation
|
|
const sidebar = screen.getByRole('navigation');
|
|
const anchor = getByText(sidebar, 'Registration');
|
|
|
|
// load from sidebar
|
|
anchor.click();
|
|
});
|
|
|
|
test('clicking Next loads Packages', () => {
|
|
const [ next, , ] = verifyButtons();
|
|
next.click();
|
|
|
|
screen.getByText('Optionally add additional packages to your image');
|
|
});
|
|
|
|
test('clicking Back loads Upload to AWS', () => {
|
|
const [ , back, ] = verifyButtons();
|
|
back.click();
|
|
|
|
screen.getByText('AWS account ID');
|
|
});
|
|
|
|
test('clicking Cancel loads landing page', () => {
|
|
const [ , , cancel ] = verifyButtons();
|
|
verifyCancelButton(cancel, historySpy);
|
|
});
|
|
|
|
test('should allow choosing activation keys', async () => {
|
|
screen
|
|
.getByLabelText('Embed an activation key and register systems on first boot')
|
|
.click();
|
|
|
|
const organizationId = screen.getByLabelText('Organization ID');
|
|
expect(organizationId).toHaveValue('5');
|
|
expect(organizationId).toBeDisabled();
|
|
|
|
// can't getByLabelText b/c the label contains an extra <span>
|
|
// with a `*` to denote required
|
|
const activationKey = screen.getByTestId('subscription-activation');
|
|
expect(activationKey).toHaveValue('');
|
|
expect(activationKey).toBeEnabled();
|
|
expect(activationKey).toBeRequired();
|
|
|
|
const sidebar = screen.getByRole('navigation');
|
|
const anchor = getByText(sidebar, 'Review');
|
|
anchor.click();
|
|
await screen.findByText('Register the system on first boot');
|
|
});
|
|
|
|
test('should hide input fields when clicking Register the system later', async () => {
|
|
// first check the other radio button which causes extra widgets to be shown
|
|
screen
|
|
.getByLabelText('Embed an activation key and register systems on first boot')
|
|
.click();
|
|
|
|
const p1 = waitForElementToBeRemoved(() => [
|
|
screen.getByTestId('organization-id'),
|
|
screen.getByTestId('subscription-activation'),
|
|
]);
|
|
|
|
// then click the first radio button which should remove any input fields
|
|
screen
|
|
.getByTestId('register-later-radio-button')
|
|
.click();
|
|
|
|
await p1;
|
|
|
|
const sidebar = screen.getByRole('navigation');
|
|
const anchor = getByText(sidebar, 'Review');
|
|
anchor.click();
|
|
await screen.findByText('Register the system later');
|
|
});
|
|
});
|
|
|
|
describe('Step Packages', () => {
|
|
beforeEach(() => {
|
|
const { _component, history } = renderWithReduxRouter(<CreateImageWizard />);
|
|
historySpy = jest.spyOn(history, 'push');
|
|
|
|
// select aws as upload destination
|
|
const awsTile = screen.getByTestId('upload-aws');
|
|
awsTile.click();
|
|
|
|
// left sidebar navigation
|
|
const sidebar = screen.getByRole('navigation');
|
|
const anchor = getByText(sidebar, 'Packages');
|
|
|
|
// load from sidebar
|
|
anchor.click();
|
|
});
|
|
|
|
test('clicking Next loads Review', () => {
|
|
const [ next, , ] = verifyButtons();
|
|
next.click();
|
|
|
|
screen.getByText('Review the information and click Create image to create the image using the following criteria.');
|
|
});
|
|
|
|
test('clicking Back loads Register', () => {
|
|
const back = screen.getByRole('button', { name: /Back/ });
|
|
back.click();
|
|
|
|
screen.getByText('Register the system');
|
|
});
|
|
|
|
test('clicking Cancel loads landing page', () => {
|
|
const [ , , cancel ] = verifyButtons();
|
|
verifyCancelButton(cancel, historySpy);
|
|
});
|
|
|
|
test('should display search bar and button', () => {
|
|
const search = screen.getByRole('searchbox', { name: 'Available search input' });
|
|
search.click();
|
|
|
|
userEvent.type(search, 'test');
|
|
|
|
screen.getByRole('button', {
|
|
name: 'Search button for available packages'
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Step Review', () => {
|
|
beforeEach(() => {
|
|
const { _component, history } = renderWithReduxRouter(<CreateImageWizard />);
|
|
historySpy = jest.spyOn(history, 'push');
|
|
|
|
// select aws as upload destination
|
|
const awsTile = screen.getByTestId('upload-aws');
|
|
awsTile.click();
|
|
|
|
// left sidebar navigation
|
|
const sidebar = screen.getByRole('navigation');
|
|
const anchor = getByText(sidebar, 'Review');
|
|
|
|
// load from sidebar
|
|
anchor.click();
|
|
});
|
|
|
|
test('has 3 buttons', () => {
|
|
screen.getByRole('button', { name: /Create/ });
|
|
screen.getByRole('button', { name: /Back/ });
|
|
screen.getByRole('button', { name: /Cancel/ });
|
|
});
|
|
|
|
test('clicking Back loads Packages', () => {
|
|
const back = screen.getByRole('button', { name: /Back/ });
|
|
back.click();
|
|
|
|
screen.getByText('Optionally add additional packages to your image');
|
|
});
|
|
|
|
test('clicking Cancel loads landing page', () => {
|
|
const cancel = screen.getByRole('button', { name: /Cancel/ });
|
|
verifyCancelButton(cancel, historySpy);
|
|
});
|
|
});
|
|
|
|
describe('Click through all steps', () => {
|
|
beforeEach(() => {
|
|
const { _component, history } = renderWithReduxRouter(<CreateImageWizard />);
|
|
historySpy = jest.spyOn(history, 'push');
|
|
});
|
|
|
|
test('with valid values', async () => {
|
|
const next = screen.getByRole('button', { name: /Next/ });
|
|
|
|
// select image output
|
|
userEvent.selectOptions(screen.getByTestId('release-select'), [ 'rhel-8' ]);
|
|
screen.getByTestId('upload-aws').click();
|
|
screen.getByTestId('upload-google').click();
|
|
next.click();
|
|
|
|
// select upload target
|
|
userEvent.type(screen.getByTestId('aws-account-id'), '012345678901');
|
|
next.click();
|
|
|
|
userEvent.type(screen.getByTestId('input-google-user'), 'test@test.com');
|
|
next.click();
|
|
|
|
// registration
|
|
screen
|
|
.getByLabelText('Embed an activation key and register systems on first boot')
|
|
.click();
|
|
await screen.findByTestId('subscription-activation');
|
|
userEvent.type(screen.getByTestId('subscription-activation'), '1234567890');
|
|
next.click();
|
|
|
|
// packages
|
|
screen.getByText('Optionally add additional packages to your image');
|
|
next.click();
|
|
|
|
// review
|
|
await screen.
|
|
findByText('Review the information and click Create image to create the image using the following criteria.');
|
|
const main = screen.getByRole('main', { name: 'Create image' });
|
|
within(main).getByText('Amazon Web Services');
|
|
within(main).getByText('Google Cloud Platform');
|
|
await screen.findByText('Register the system on first boot');
|
|
|
|
// mock the backend API
|
|
const composeImage = jest.spyOn(api, 'composeImage');
|
|
composeImage.mockResolvedValue({ id: 'test-me' });
|
|
|
|
const create = screen.getByRole('button', { name: /Create/ });
|
|
create.click();
|
|
|
|
// API request sent to backend
|
|
await expect(composeImage).toHaveBeenCalledTimes(2);
|
|
|
|
// returns back to the landing page
|
|
// but jsdom will not render the new page so we can't assert on that
|
|
await waitFor(() => expect(historySpy).toHaveBeenCalledTimes(1));
|
|
await expect(historySpy).toHaveBeenCalledWith('/landing');
|
|
});
|
|
|
|
test('with missing values', async () => {
|
|
const next = screen.getByRole('button', { name: /Next/ });
|
|
|
|
// select release
|
|
userEvent.selectOptions(screen.getByTestId('release-select'), [ 'rhel-8' ]);
|
|
screen.getByTestId('upload-aws').click();
|
|
next.click();
|
|
|
|
// leave AWS account id empty
|
|
next.click();
|
|
|
|
// registration
|
|
screen
|
|
.getByLabelText('Embed an activation key and register systems on first boot')
|
|
.click();
|
|
await screen.findByTestId('subscription-activation');
|
|
userEvent.clear(screen.getByTestId('subscription-activation'));
|
|
next.click();
|
|
|
|
// packages
|
|
screen.getByText('Optionally add additional packages to your image');
|
|
next.click();
|
|
|
|
await screen.
|
|
findByText('Review the information and click Create image to create the image using the following criteria.');
|
|
const main = screen.getByRole('main', { name: 'Create image' });
|
|
within(main).getByText('Amazon Web Services');
|
|
await screen.findByText('Register the system on first boot');
|
|
|
|
const errorMessages = await screen.findAllByText('A value is required');
|
|
expect(errorMessages.length).toBe(1);
|
|
|
|
const uploadErrorMessage = await screen.findAllByText('A 12-digit number is required');
|
|
expect(uploadErrorMessage.length).toBe(1);
|
|
});
|
|
|
|
test('with invalid values', async () => {
|
|
const next = screen.getByRole('button', { name: /Next/ });
|
|
|
|
// select release
|
|
userEvent.selectOptions(screen.getByTestId('release-select'), [ 'rhel-8' ]);
|
|
// select upload target
|
|
screen.getByTestId('upload-aws').click();
|
|
next.click();
|
|
|
|
userEvent.type(screen.getByTestId('aws-account-id'), 'invalid, isNaN');
|
|
next.click();
|
|
|
|
// registration
|
|
screen
|
|
.getByLabelText('Embed an activation key and register systems on first boot')
|
|
.click();
|
|
await screen.findByTestId('subscription-activation');
|
|
userEvent.clear(screen.getByTestId('subscription-activation'));
|
|
next.click();
|
|
|
|
// packages
|
|
screen.getByText('Optionally add additional packages to your image');
|
|
next.click();
|
|
|
|
await screen.
|
|
findByText('Review the information and click Create image to create the image using the following criteria.');
|
|
const main = screen.getByRole('main', { name: 'Create image' });
|
|
within(main).getByText('Amazon Web Services');
|
|
await screen.findByText('Register the system on first boot');
|
|
|
|
const errorMessages = await screen.findAllByText('A value is required');
|
|
expect(errorMessages.length).toBe(1);
|
|
|
|
const uploadErrorMessage = await screen.findAllByText('A 12-digit number is required');
|
|
expect(uploadErrorMessage.length).toBe(1);
|
|
});
|
|
});
|