Skip to content

Commit

Permalink
feat(secrets): add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
abhinandan13jan committed Oct 22, 2024
1 parent 70bf4ea commit 0c72f5a
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 13 deletions.
5 changes: 4 additions & 1 deletion src/components/Secrets/SecretForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type SecretFormProps = RawComponentProps & {

const SecretForm: React.FC<React.PropsWithChildren<SecretFormProps>> = ({ existingSecrets }) => {
const { values, setFieldValue } = useFormikContext<SecretFormValues>();

const defaultKeyValues = [{ key: '', value: '', readOnlyKey: false }];
const defaultImageKeyValues = [{ key: '.dockerconfigjson', value: '', readOnlyKey: true }];

Expand Down Expand Up @@ -109,7 +110,9 @@ const SecretForm: React.FC<React.PropsWithChildren<SecretFormProps>> = ({ existi
{currentType !== SecretTypeDropdownLabel.source && (
<KeyValueFileInputField
required
name="keyValues"
name={
currentType === SecretTypeDropdownLabel.opaque ? 'opaque.keyValues' : 'image.keyValues'
}
data-test="secret-key-value-pair"
entries={defaultKeyValues}
disableRemoveAction={values.opaque.keyValues.length === 1}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Secrets/SecretModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from '@patternfly/react-core';
import { Formik } from 'formik';
import { isEmpty } from 'lodash-es';
import { ImportSecret, SecretTypeDropdownLabel } from '../../types';
import { ImportSecret, SecretTypeDropdownLabel, SourceSecretType } from '../../types';
import { SecretFromSchema } from '../../utils/validation-utils';
import { RawComponentProps } from '../modal/createModalLauncher';
import SecretForm from './SecretForm';
Expand Down Expand Up @@ -50,7 +50,7 @@ const SecretModal: React.FC<React.PropsWithChildren<SecretModalProps>> = ({
keyValues: defaultKeyValues,
},
source: {
authType: 'Basic authentication',
authType: SourceSecretType.basic,
},
existingSecrets,
};
Expand Down
6 changes: 3 additions & 3 deletions src/types/secret.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ export const SecretByUILabel = 'ui.appstudio.redhat.com/secret-for';
export type ImportSecret = {
secretName: string;
type: string;
source: Source;
opaque: {
source?: Source;
opaque?: {
keyValues: {
key: string;
value: string;
readOnlyKey?: boolean;
}[];
};
image: {
image?: {
keyValues: {
key: string;
value: string;
Expand Down
84 changes: 80 additions & 4 deletions src/utils/__tests__/create-utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SPIAccessTokenBindingKind,
SecretFor,
SecretTypeDropdownLabel,
SourceSecretType,
} from '../../types';
import { ApplicationModel } from './../../models/application';
import { ComponentDetectionQueryModel, ComponentModel } from './../../models/component';
Expand Down Expand Up @@ -497,7 +498,7 @@ describe('Create Utils', () => {
{
secretName: 'my-snyk-secret',
type: SecretTypeDropdownLabel.opaque,
keyValues: [{ key: 'token', value: 'my-token-data' }],
opaque: { keyValues: [{ key: 'token', value: 'my-token-data' }] },
},
'test-ws',
'test-ns',
Expand All @@ -522,7 +523,7 @@ describe('Create Utils', () => {
{
secretName: 'my-snyk-secret',
type: SecretTypeDropdownLabel.opaque,
keyValues: [{ key: 'token', value: 'my-token-data' }],
opaque: { keyValues: [{ key: 'token', value: 'my-token-data' }] },
},
'test-ws',
'test-ns',
Expand All @@ -547,7 +548,7 @@ describe('Create Utils', () => {
{
secretName: 'registry-creds',
type: SecretTypeDropdownLabel.image,
keyValues: [{ key: 'token', value: 'my-token-data' }],
image: { keyValues: [{ key: 'token', value: 'my-token-data' }] },
},
'test-ws',
'test-ns',
Expand All @@ -564,6 +565,81 @@ describe('Create Utils', () => {
);
});

it('should add correct values for Image pull secret', async () => {
commonFetchMock.mockClear();
commonFetchMock.mockImplementationOnce((props) => Promise.resolve(props));

await createSecret(
{
secretName: 'registry-creds',
type: SecretTypeDropdownLabel.image,
image: { keyValues: [{ key: 'test', value: 'test-value' }] },
},
'test-ws',
'test-ns',
false,
);

expect(commonFetchMock).toHaveBeenCalledTimes(1);

expect(commonFetchMock).toHaveBeenCalledWith(
'/workspaces/test-ws/api/v1/namespaces/test-ns/secrets',
expect.objectContaining({
body: expect.stringContaining('"test":"test-value"'),
}),
);
});

it('should create a Source secret', async () => {
commonFetchMock.mockClear();
commonFetchMock.mockImplementationOnce((props) => Promise.resolve(props));

await createSecret(
{
secretName: 'registry-creds',
type: SecretTypeDropdownLabel.source,
source: { authType: SourceSecretType.basic, username: 'test1', password: 'pass-test' },
},
'test-ws',
'test-ns',
false,
);

expect(commonFetchMock).toHaveBeenCalledTimes(1);

expect(commonFetchMock).toHaveBeenCalledWith(
'/workspaces/test-ws/api/v1/namespaces/test-ns/secrets',
expect.objectContaining({
body: expect.stringContaining('"type":"kubernetes.io/basic-auth"'),
}),
);
});

it('should add correct data for Source secret', async () => {
commonFetchMock.mockClear();
commonFetchMock.mockImplementationOnce((props) => Promise.resolve(props));

await createSecret(
{
secretName: 'registry-creds',
type: SecretTypeDropdownLabel.source,
source: { authType: SourceSecretType.basic, username: 'test1', password: 'pass-test' },
},
'test-ws',
'test-ns',
false,
);

expect(commonFetchMock).toHaveBeenCalledTimes(1);

expect(commonFetchMock).toHaveBeenCalledWith(
'/workspaces/test-ws/api/v1/namespaces/test-ns/secrets',
expect.objectContaining({
body: expect.stringContaining('"username":"dGVzdDE=","password":"cGFzcy10ZXN0"'),
}),
);
});

it('should create partner task secret', async () => {
commonFetchMock.mockClear();
createResourceMock
Expand All @@ -575,7 +651,7 @@ describe('Create Utils', () => {
{
secretName: 'snyk-secret',
type: SecretTypeDropdownLabel.opaque,
keyValues: [{ key: 'token', value: 'my-token-data' }],
opaque: { keyValues: [{ key: 'token', value: 'my-token-data' }] },
},
'test-ws',
'test-ns',
Expand Down
13 changes: 10 additions & 3 deletions src/utils/create-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,11 @@ export const getSecretObject = (values: SecretFormValues, namespace: string): Se
data[SSH_KEY] = values.source[SSH_KEY];
}
} else {
data = values.opaque.keyValues.reduce((acc, s) => {
const keyValues =
values.type === SecretTypeDropdownLabel.opaque
? values.opaque.keyValues
: values.image.keyValues;
data = keyValues?.reduce((acc, s) => {
acc[s.key] = s.value ? s.value : '';
return acc;
}, {});
Expand All @@ -387,8 +391,11 @@ export const getSecretObject = (values: SecretFormValues, namespace: string): Se
name: values.secretName,
namespace,
},
type: K8sSecretType[values.type],
data,
type:
values.type === SecretTypeDropdownLabel.source
? K8sSecretType[values.source?.authType]
: K8sSecretType[values.type],
stringData: data,
};

return secretResource;
Expand Down
11 changes: 11 additions & 0 deletions src/utils/validation-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,15 @@ export const SecretFromSchema = yup.object({
),
}),
}),
image: yup.object().when('type', {
is: SecretTypeDropdownLabel.image,
then: yup.object({
keyValues: yup.array().of(
yup.object({
key: yup.string().required('Required'),
value: yup.string().required('Required'),
}),
),
}),
}),
});

0 comments on commit 0c72f5a

Please sign in to comment.