diff --git a/awx/ui_next/src/api/models/CredentialTypes.js b/awx/ui_next/src/api/models/CredentialTypes.js
index 65906cdcbd..d2d993091c 100644
--- a/awx/ui_next/src/api/models/CredentialTypes.js
+++ b/awx/ui_next/src/api/models/CredentialTypes.js
@@ -5,6 +5,28 @@ class CredentialTypes extends Base {
super(http);
this.baseUrl = '/api/v2/credential_types/';
}
+
+ async loadAllTypes(
+ acceptableKinds = ['machine', 'cloud', 'net', 'ssh', 'vault']
+ ) {
+ const pageSize = 200;
+ // The number of credential types a user can have is unlimited. In practice, it is unlikely for
+ // users to have more than a page at the maximum request size.
+ const {
+ data: { next, results },
+ } = await this.read({ page_size: pageSize });
+ let nextResults = [];
+ if (next) {
+ const { data } = await this.read({
+ page_size: pageSize,
+ page: 2,
+ });
+ nextResults = data.results;
+ }
+ return results
+ .concat(nextResults)
+ .filter(type => acceptableKinds.includes(type.kind));
+ }
}
export default CredentialTypes;
diff --git a/awx/ui_next/src/api/models/CredentialTypes.test.js b/awx/ui_next/src/api/models/CredentialTypes.test.js
new file mode 100644
index 0000000000..5cb038912e
--- /dev/null
+++ b/awx/ui_next/src/api/models/CredentialTypes.test.js
@@ -0,0 +1,65 @@
+import CredentialTypes from './CredentialTypes';
+
+const typesData = [{ id: 1, kind: 'machine' }, { id: 2, kind: 'cloud' }];
+
+describe('CredentialTypesAPI', () => {
+ test('should load all types', async () => {
+ const getPromise = () =>
+ Promise.resolve({
+ data: {
+ results: typesData,
+ },
+ });
+ const mockHttp = { get: jest.fn(getPromise) };
+ const CredentialTypesAPI = new CredentialTypes(mockHttp);
+
+ const types = await CredentialTypesAPI.loadAllTypes();
+
+ expect(mockHttp.get).toHaveBeenCalledTimes(1);
+ expect(mockHttp.get.mock.calls[0]).toEqual([
+ `/api/v2/credential_types/`,
+ { params: { page_size: 200 } },
+ ]);
+ expect(types).toEqual(typesData);
+ });
+
+ test('should load all types (2 pages)', async () => {
+ const getPromise = () =>
+ Promise.resolve({
+ data: {
+ results: typesData,
+ next: 2,
+ },
+ });
+ const mockHttp = { get: jest.fn(getPromise) };
+ const CredentialTypesAPI = new CredentialTypes(mockHttp);
+
+ const types = await CredentialTypesAPI.loadAllTypes();
+
+ expect(mockHttp.get).toHaveBeenCalledTimes(2);
+ expect(mockHttp.get.mock.calls[0]).toEqual([
+ `/api/v2/credential_types/`,
+ { params: { page_size: 200 } },
+ ]);
+ expect(mockHttp.get.mock.calls[1]).toEqual([
+ `/api/v2/credential_types/`,
+ { params: { page_size: 200, page: 2 } },
+ ]);
+ expect(types).toHaveLength(4);
+ });
+
+ test('should filter by acceptable kinds', async () => {
+ const getPromise = () =>
+ Promise.resolve({
+ data: {
+ results: typesData,
+ },
+ });
+ const mockHttp = { get: jest.fn(getPromise) };
+ const CredentialTypesAPI = new CredentialTypes(mockHttp);
+
+ const types = await CredentialTypesAPI.loadAllTypes(['machine']);
+
+ expect(types).toEqual([typesData[0]]);
+ });
+});
diff --git a/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx b/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx
index 58bdf359cb..c153b1d610 100644
--- a/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx
+++ b/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx
@@ -17,27 +17,6 @@ const QS_CONFIG = getQSConfig('credentials', {
order_by: 'name',
});
-async function loadCredentialTypes() {
- const pageSize = 200;
- const acceptableKinds = ['machine', 'cloud', 'net', 'ssh', 'vault'];
- // The number of credential types a user can have is unlimited. In practice, it is unlikely for
- // users to have more than a page at the maximum request size.
- const {
- data: { next, results },
- } = await CredentialTypesAPI.read({ page_size: pageSize });
- let nextResults = [];
- if (next) {
- const { data } = await CredentialTypesAPI.read({
- page_size: pageSize,
- page: 2,
- });
- nextResults = data.results;
- }
- return results
- .concat(nextResults)
- .filter(type => acceptableKinds.includes(type.kind));
-}
-
async function loadCredentials(params, selectedCredentialTypeId) {
params.credential_type = selectedCredentialTypeId || 1;
const { data } = await CredentialsAPI.read(params);
@@ -54,7 +33,7 @@ function MultiCredentialsLookup(props) {
useEffect(() => {
(async () => {
try {
- const types = await loadCredentialTypes();
+ const types = await CredentialTypesAPI.loadAllTypes();
setCredentialTypes(types);
const match = types.find(type => type.kind === 'ssh') || types[0];
setSelectedType(match);
diff --git a/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.test.jsx b/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.test.jsx
index fa8eb5a15f..08fcf87b18 100644
--- a/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.test.jsx
+++ b/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.test.jsx
@@ -18,21 +18,16 @@ describe('', () => {
];
beforeEach(() => {
- CredentialTypesAPI.read.mockResolvedValueOnce({
- data: {
- results: [
- {
- id: 400,
- kind: 'ssh',
- namespace: 'biz',
- name: 'Amazon Web Services',
- },
- { id: 500, kind: 'vault', namespace: 'buzz', name: 'Vault' },
- { id: 600, kind: 'machine', namespace: 'fuzz', name: 'Machine' },
- ],
- count: 2,
+ CredentialTypesAPI.loadAllTypes.mockResolvedValueOnce([
+ {
+ id: 400,
+ kind: 'ssh',
+ namespace: 'biz',
+ name: 'Amazon Web Services',
},
- });
+ { id: 500, kind: 'vault', namespace: 'buzz', name: 'Vault' },
+ { id: 600, kind: 'machine', namespace: 'fuzz', name: 'Machine' },
+ ]);
CredentialsAPI.read.mockResolvedValueOnce({
data: {
results: [
@@ -52,7 +47,7 @@ describe('', () => {
wrapper.unmount();
});
- test('MultiCredentialsLookup renders properly', async () => {
+ test('should load credential types', async () => {
const onChange = jest.fn();
await act(async () => {
wrapper = mountWithContexts(
@@ -64,8 +59,9 @@ describe('', () => {
/>
);
});
+ wrapper.update();
expect(wrapper.find('MultiCredentialsLookup')).toHaveLength(1);
- expect(CredentialTypesAPI.read).toHaveBeenCalled();
+ expect(CredentialTypesAPI.loadAllTypes).toHaveBeenCalled();
});
test('onChange is called when you click to remove a credential from input', async () => {
@@ -118,12 +114,12 @@ describe('', () => {
count: 1,
},
});
- expect(CredentialsAPI.read).toHaveBeenCalledTimes(2);
+ expect(CredentialsAPI.read).toHaveBeenCalledTimes(1);
await act(async () => {
select.invoke('onChange')({}, 500);
});
wrapper.update();
- expect(CredentialsAPI.read).toHaveBeenCalledTimes(3);
+ expect(CredentialsAPI.read).toHaveBeenCalledTimes(2);
expect(wrapper.find('OptionsList').prop('options')).toEqual([
{ id: 1, kind: 'cloud', name: 'New Cred', url: 'www.google.com' },
]);