Adds a bit more unit test coverage around credential add/edit save functionality, making sure that we're making the correct calls with the correct payloads.

This commit is contained in:
mabashian
2020-06-09 13:58:40 -04:00
parent 9d63b679f9
commit 9180334908
2 changed files with 237 additions and 190 deletions

View File

@@ -6,7 +6,11 @@ import {
waitForElement, waitForElement,
} from '../../../../testUtils/enzymeHelpers'; } from '../../../../testUtils/enzymeHelpers';
import { CredentialsAPI, CredentialTypesAPI } from '../../../api'; import {
CredentialsAPI,
CredentialInputSourcesAPI,
CredentialTypesAPI,
} from '../../../api';
import CredentialAdd from './CredentialAdd'; import CredentialAdd from './CredentialAdd';
jest.mock('../../../api'); jest.mock('../../../api');
@@ -14,58 +18,6 @@ jest.mock('../../../api');
CredentialTypesAPI.read.mockResolvedValue({ CredentialTypesAPI.read.mockResolvedValue({
data: { data: {
results: [ results: [
{
id: 2,
type: 'credential_type',
url: '/api/v2/credential_types/2/',
related: {
credentials: '/api/v2/credential_types/2/credentials/',
activity_stream: '/api/v2/credential_types/2/activity_stream/',
},
summary_fields: {
user_capabilities: {
edit: false,
delete: false,
},
},
created: '2020-02-12T19:42:43.551238Z',
modified: '2020-02-12T19:43:03.164800Z',
name: 'Source Control',
description: '',
kind: 'scm',
namespace: 'scm',
managed_by_tower: true,
inputs: {
fields: [
{
id: 'username',
label: 'Username',
type: 'string',
},
{
id: 'password',
label: 'Password',
type: 'string',
secret: true,
},
{
id: 'ssh_key_data',
label: 'Source Control Private Key',
type: 'string',
format: 'ssh_private_key',
secret: true,
multiline: true,
},
{
id: 'ssh_key_unlock',
label: 'Private Key Passphrase',
type: 'string',
secret: true,
},
],
},
injectors: {},
},
{ {
id: 1, id: 1,
type: 'credential_type', type: 'credential_type',
@@ -156,59 +108,98 @@ describe('<CredentialAdd />', () => {
let wrapper; let wrapper;
let history; let history;
beforeEach(async () => { describe('Initial GET request succeeds', () => {
history = createMemoryHistory({ initialEntries: ['/credentials'] }); beforeEach(async () => {
await act(async () => { history = createMemoryHistory({ initialEntries: ['/credentials'] });
wrapper = mountWithContexts(<CredentialAdd />, { await act(async () => {
context: { router: { history } }, wrapper = mountWithContexts(<CredentialAdd />, {
context: { router: { history } },
});
}); });
}); });
});
afterEach(() => { afterEach(() => {
wrapper.unmount(); wrapper.unmount();
}); });
test('Initially renders successfully', () => { test('handleSubmit should call the api and redirect to details page', async () => {
expect(wrapper.length).toBe(1); await waitForElement(wrapper, 'isLoading', el => el.length === 0);
}); await act(async () => {
test('handleSubmit should call the api and redirect to details page', async () => { wrapper.find('CredentialForm').prop('onSubmit')({
await waitForElement(wrapper, 'isLoading', el => el.length === 0); user: 1,
await act(async () => { organization: null,
wrapper.find('CredentialForm').prop('onSubmit')({ name: 'foo',
description: 'bar',
credential_type: '1',
inputs: {
username: {
credential: {
id: 1,
name: 'Some cred',
},
inputs: {
foo: 'bar',
},
},
password: 'foo',
ssh_key_data: 'bar',
ssh_public_key_data: 'baz',
ssh_key_unlock: 'foobar',
become_method: '',
become_username: '',
become_password: '',
},
passwordPrompts: {
become_password: true,
},
});
});
expect(CredentialsAPI.create).toHaveBeenCalledWith({
user: 1, user: 1,
organization: null, organization: null,
name: 'foo', name: 'foo',
description: 'bar', description: 'bar',
credential_type: '2', credential_type: '1',
inputs: { inputs: {
username: '', password: 'foo',
password: '', ssh_key_data: 'bar',
ssh_key_data: '', ssh_public_key_data: 'baz',
ssh_key_unlock: '', ssh_key_unlock: 'foobar',
become_method: '',
become_username: '',
become_password: 'ASK',
}, },
passwordPrompts: {},
}); });
expect(CredentialInputSourcesAPI.create).toHaveBeenCalledWith({
input_field_name: 'username',
metadata: {
foo: 'bar',
},
source_credential: 1,
target_credential: 13,
});
expect(history.location.pathname).toBe('/credentials/13/details');
}); });
expect(CredentialsAPI.create).toHaveBeenCalledWith({
user: 1, test('handleCancel should return the user back to the inventories list', async () => {
organization: null, await waitForElement(wrapper, 'isLoading', el => el.length === 0);
name: 'foo', wrapper.find('Button[aria-label="Cancel"]').simulate('click');
description: 'bar', expect(history.location.pathname).toEqual('/credentials');
credential_type: '2',
inputs: {
username: '',
password: '',
ssh_key_data: '',
ssh_key_unlock: '',
},
}); });
expect(history.location.pathname).toBe('/credentials/13/details');
}); });
test('handleCancel should return the user back to the inventories list', async () => { describe('Initial GET request fails', () => {
await waitForElement(wrapper, 'isLoading', el => el.length === 0); test('shows error when initial GET request fails', async () => {
wrapper.find('Button[aria-label="Cancel"]').simulate('click'); CredentialTypesAPI.read.mockRejectedValue(new Error());
expect(history.location.pathname).toEqual('/credentials'); history = createMemoryHistory({ initialEntries: ['/credentials'] });
await act(async () => {
wrapper = mountWithContexts(<CredentialAdd />, {
context: { router: { history } },
});
});
wrapper.update();
expect(wrapper.find('ContentError').length).toBe(1);
wrapper.unmount();
});
}); });
}); });

View File

@@ -6,7 +6,11 @@ import {
waitForElement, waitForElement,
} from '../../../../testUtils/enzymeHelpers'; } from '../../../../testUtils/enzymeHelpers';
import { CredentialsAPI, CredentialTypesAPI } from '../../../api'; import {
CredentialsAPI,
CredentialInputSourcesAPI,
CredentialTypesAPI,
} from '../../../api';
import CredentialEdit from './CredentialEdit'; import CredentialEdit from './CredentialEdit';
jest.mock('../../../api'); jest.mock('../../../api');
@@ -107,58 +111,6 @@ const mockCredential = {
CredentialTypesAPI.read.mockResolvedValue({ CredentialTypesAPI.read.mockResolvedValue({
data: { data: {
results: [ results: [
{
id: 2,
type: 'credential_type',
url: '/api/v2/credential_types/2/',
related: {
credentials: '/api/v2/credential_types/2/credentials/',
activity_stream: '/api/v2/credential_types/2/activity_stream/',
},
summary_fields: {
user_capabilities: {
edit: false,
delete: false,
},
},
created: '2020-02-12T19:42:43.551238Z',
modified: '2020-02-12T19:43:03.164800Z',
name: 'Source Control',
description: '',
kind: 'scm',
namespace: 'scm',
managed_by_tower: true,
inputs: {
fields: [
{
id: 'username',
label: 'Username',
type: 'string',
},
{
id: 'password',
label: 'Password',
type: 'string',
secret: true,
},
{
id: 'ssh_key_data',
label: 'Source Control Private Key',
type: 'string',
format: 'ssh_private_key',
secret: true,
multiline: true,
},
{
id: 'ssh_key_unlock',
label: 'Private Key Passphrase',
type: 'string',
secret: true,
},
],
},
injectors: {},
},
{ {
id: 1, id: 1,
type: 'credential_type', type: 'credential_type',
@@ -244,69 +196,173 @@ CredentialTypesAPI.read.mockResolvedValue({
}); });
CredentialsAPI.update.mockResolvedValue({ data: { id: 3 } }); CredentialsAPI.update.mockResolvedValue({ data: { id: 3 } });
CredentialsAPI.readInputSources.mockResolvedValue({ data: { results: [] } }); CredentialsAPI.readInputSources.mockResolvedValue({
data: {
results: [
{
id: 34,
summary_fields: {
source_credential: {
id: 20,
name: 'CyberArk Conjur Secret Lookup',
description: '',
kind: 'conjur',
cloud: false,
credential_type_id: 20,
},
},
input_field_name: 'password',
metadata: {
secret_path: 'a',
secret_version: 'b',
},
source_credential: 20,
},
{
id: 35,
summary_fields: {
source_credential: {
id: 20,
name: 'CyberArk Conjur Secret Lookup',
description: '',
kind: 'conjur',
cloud: false,
credential_type_id: 20,
},
},
input_field_name: 'become_username',
metadata: {
secret_path: 'foo',
secret_version: 'bar',
},
source_credential: 20,
},
],
},
});
describe('<CredentialEdit />', () => { describe('<CredentialEdit />', () => {
let wrapper; let wrapper;
let history; let history;
beforeEach(async () => { describe('Initial GET request succeeds', () => {
history = createMemoryHistory({ initialEntries: ['/credentials'] }); beforeEach(async () => {
await act(async () => { history = createMemoryHistory({ initialEntries: ['/credentials'] });
wrapper = mountWithContexts( await act(async () => {
<CredentialEdit credential={mockCredential} />, wrapper = mountWithContexts(
{ <CredentialEdit credential={mockCredential} />,
context: { router: { history } }, {
} context: { router: { history } },
); }
);
});
}); });
});
afterEach(() => { afterEach(() => {
wrapper.unmount(); wrapper.unmount();
}); });
test('initially renders successfully', async () => { test('initially renders successfully', async () => {
expect(wrapper.find('CredentialEdit').length).toBe(1); expect(wrapper.find('CredentialEdit').length).toBe(1);
}); });
test('handleCancel returns the user to credential detail', async () => { test('handleCancel returns the user to credential detail', async () => {
await waitForElement(wrapper, 'isLoading', el => el.length === 0); await waitForElement(wrapper, 'isLoading', el => el.length === 0);
wrapper.find('Button[aria-label="Cancel"]').simulate('click'); wrapper.find('Button[aria-label="Cancel"]').simulate('click');
expect(history.location.pathname).toEqual('/credentials/3/details'); expect(history.location.pathname).toEqual('/credentials/3/details');
}); });
test('handleSubmit should post to the api', async () => { test('handleSubmit should post to the api', async () => {
await waitForElement(wrapper, 'isLoading', el => el.length === 0); await waitForElement(wrapper, 'isLoading', el => el.length === 0);
await act(async () => { await act(async () => {
wrapper.find('CredentialForm').prop('onSubmit')({ wrapper.find('CredentialForm').prop('onSubmit')({
user: 1,
organization: null,
name: 'foo',
description: 'bar',
credential_type: '1',
inputs: {
username: {
credential: {
id: 1,
name: 'Some cred',
},
inputs: {
foo: 'bar',
},
},
password: 'foo',
ssh_key_data: 'bar',
ssh_public_key_data: 'baz',
ssh_key_unlock: 'foobar',
become_method: '',
become_username: {
credential: {
id: 1,
name: 'Some cred',
},
inputs: {
secret_path: '/foo/bar',
secret_version: '9000',
},
touched: true,
},
become_password: '',
},
passwordPrompts: {
become_password: true,
},
});
});
expect(CredentialsAPI.update).toHaveBeenCalledWith(3, {
user: 1, user: 1,
organization: null, organization: null,
name: 'foo', name: 'foo',
description: 'bar', description: 'bar',
credential_type: '2', credential_type: '1',
inputs: { inputs: {
username: '', password: 'foo',
password: '', ssh_key_data: 'bar',
ssh_key_data: '', ssh_public_key_data: 'baz',
ssh_key_unlock: '', ssh_key_unlock: 'foobar',
become_method: '',
become_password: 'ASK',
}, },
passwordPrompts: {},
}); });
expect(CredentialInputSourcesAPI.create).toHaveBeenCalledWith({
input_field_name: 'username',
metadata: {
foo: 'bar',
},
source_credential: 1,
target_credential: 3,
});
expect(CredentialInputSourcesAPI.update).toHaveBeenCalledWith(35, {
metadata: {
secret_path: '/foo/bar',
secret_version: '9000',
},
source_credential: 1,
});
expect(CredentialInputSourcesAPI.destroy).toHaveBeenCalledWith(34);
expect(history.location.pathname).toBe('/credentials/3/details');
}); });
expect(CredentialsAPI.update).toHaveBeenCalledWith(3, { });
user: 1, describe('Initial GET request fails', () => {
organization: null, test('shows error when initial GET request fails', async () => {
name: 'foo', CredentialTypesAPI.read.mockRejectedValue(new Error());
description: 'bar', history = createMemoryHistory({ initialEntries: ['/credentials'] });
credential_type: '2', await act(async () => {
inputs: { wrapper = mountWithContexts(
username: '', <CredentialEdit credential={mockCredential} />,
password: '', {
ssh_key_data: '', context: { router: { history } },
ssh_key_unlock: '', }
}, );
});
wrapper.update();
expect(wrapper.find('ContentError').length).toBe(1);
wrapper.unmount();
}); });
expect(history.location.pathname).toBe('/credentials/3/details');
}); });
}); });