-
Notifications
You must be signed in to change notification settings - Fork 357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: [M3-7160] - Add AGLB "Edit Certificate" drawer #9723
Changes from all commits
a0996b6
34a4ffd
06f0886
61f2999
1366934
8e9854d
ae8cf08
499247b
caaf647
101f015
6a6d1d6
816ee30
f79299a
3269b33
30e80a7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,7 @@ import { | |
} from '@linode/api-v4/lib/aglb/types'; | ||
import * as Factory from 'factory.ts'; | ||
|
||
const certificate = ` | ||
export const mockCertificate = ` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I preemptively renamed in hope of making it clear that these are not real values that are a cause of security concern. |
||
-----BEGIN CERTIFICATE----- | ||
MIID0DCCArigAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJGUjET | ||
MBEGA1UECAwKU29tZS1TdGF0ZTEOMAwGA1UEBwwFUGFyaXMxDTALBgNVBAoMBERp | ||
|
@@ -39,7 +39,7 @@ cbTV5RDkrlaYwm5yqlTIglvCv7o= | |
-----END CERTIFICATE----- | ||
`; | ||
|
||
const key = ` | ||
const mockKey = ` | ||
-----BEGIN RSA PRIVATE KEY----- | ||
MIIEowIBAAKCAQEAvpnaPKLIKdvx98KW68lz8pGaRRcYersNGqPjpifMVjjE8LuC | ||
oXgPU0HePnNTUjpShBnynKCvrtWhN+haKbSp+QWXSxiTrW99HBfAl1MDQyWcukoE | ||
|
@@ -275,15 +275,16 @@ export const createServiceTargetFactory = Factory.Sync.makeFactory<ServiceTarget | |
// Certificate endpoints | ||
// ********************* | ||
export const certificateFactory = Factory.Sync.makeFactory<Certificate>({ | ||
certificate: mockCertificate, | ||
id: Factory.each((i) => i), | ||
label: Factory.each((i) => `certificate-${i}`), | ||
type: 'ca', | ||
}); | ||
|
||
export const createCertificateFactory = Factory.Sync.makeFactory<CreateCertificatePayload>( | ||
{ | ||
certificate, | ||
key, | ||
certificate: mockCertificate, | ||
key: mockKey, | ||
label: 'my-cert', | ||
type: 'downstream', | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,8 @@ import { Typography } from 'src/components/Typography'; | |
import { useLoadBalancerCertificateCreateMutation } from 'src/queries/aglb/certificates'; | ||
import { getErrorMap } from 'src/utilities/errorUtils'; | ||
|
||
import { labelMap } from './EditCertificateDrawer'; | ||
|
||
import type { Certificate, CreateCertificatePayload } from '@linode/api-v4'; | ||
|
||
interface Props { | ||
|
@@ -91,7 +93,7 @@ export const CreateCertificateDrawer = (props: Props) => { | |
/> | ||
<TextField | ||
errorText={errorMap.certificate} | ||
label="TLS Certificate" | ||
label={labelMap[type]} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Daniel updated to mocks so that the Create drawer now labels the field as "Server Certificate" for ca/service target certificates and is "TLS Certificate" for downstream/TLS, so I made the change to dynamically render the label based on |
||
labelTooltipText="TODO" | ||
multiline | ||
name="certificate" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import { Certificate } from '@linode/api-v4'; | ||
import { act, waitFor } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import React from 'react'; | ||
|
||
import { mockCertificate } from 'src/factories'; | ||
import { renderWithTheme } from 'src/utilities/testHelpers'; | ||
|
||
import { EditCertificateDrawer } from './EditCertificateDrawer'; | ||
|
||
const mockTLSCertificate: Certificate = { | ||
certificate: mockCertificate, | ||
id: 0, | ||
label: 'test-tls-cert', | ||
type: 'downstream', | ||
}; | ||
const mockCACertificate: Certificate = { | ||
certificate: mockCertificate, | ||
id: 0, | ||
label: 'test-ca-cert', | ||
type: 'ca', | ||
}; | ||
|
||
describe('EditCertificateDrawer', () => { | ||
it('should contain the name of the cert in the drawer title and label field', () => { | ||
const onClose = jest.fn(); | ||
|
||
const { getByLabelText, getByTestId } = renderWithTheme( | ||
<EditCertificateDrawer | ||
certificate={mockTLSCertificate} | ||
loadbalancerId={0} | ||
onClose={onClose} | ||
open | ||
/> | ||
); | ||
|
||
const labelInput = getByLabelText('Certificate Label'); | ||
|
||
expect(getByTestId('drawer-title')).toHaveTextContent( | ||
`Edit ${mockTLSCertificate.label}` | ||
); | ||
expect(labelInput).toHaveDisplayValue(mockTLSCertificate.label); | ||
}); | ||
|
||
it('should contain the cert in the cert field and placeholder text in the private key for a downstream cert', () => { | ||
const onClose = jest.fn(); | ||
|
||
const { getByLabelText } = renderWithTheme( | ||
<EditCertificateDrawer | ||
certificate={mockTLSCertificate} | ||
loadbalancerId={0} | ||
onClose={onClose} | ||
open | ||
/> | ||
); | ||
|
||
const certInput = getByLabelText('TLS Certificate'); | ||
const keyInput = getByLabelText('Private Key'); | ||
|
||
expect(certInput).toHaveDisplayValue(mockTLSCertificate.certificate.trim()); | ||
expect(keyInput).toHaveAttribute( | ||
'placeholder', | ||
'Private key is redacted for security.' | ||
); | ||
}); | ||
|
||
it('should submit and close drawer when only the label of the certificate is edited', async () => { | ||
const onClose = jest.fn(); | ||
|
||
const { getByLabelText, getByTestId } = renderWithTheme( | ||
<EditCertificateDrawer | ||
certificate={mockCACertificate} | ||
loadbalancerId={0} | ||
onClose={onClose} | ||
open | ||
/> | ||
); | ||
|
||
const labelInput = getByLabelText('Certificate Label'); | ||
const certInput = getByLabelText('Server Certificate'); | ||
|
||
expect(labelInput).toHaveDisplayValue(mockCACertificate.label); | ||
expect(certInput).toHaveDisplayValue(mockCACertificate.certificate.trim()); | ||
|
||
act(() => { | ||
userEvent.type(labelInput, 'my-updated-cert-0'); | ||
userEvent.click(getByTestId('submit')); | ||
}); | ||
|
||
await waitFor(() => expect(onClose).toBeCalled()); | ||
}); | ||
|
||
it('should submit and close drawer when both a certificate and key are included', async () => { | ||
const onClose = jest.fn(); | ||
|
||
const { getByLabelText, getByTestId } = renderWithTheme( | ||
<EditCertificateDrawer | ||
certificate={mockTLSCertificate} | ||
loadbalancerId={0} | ||
onClose={onClose} | ||
open | ||
/> | ||
); | ||
const labelInput = getByLabelText('Certificate Label'); | ||
const certInput = getByLabelText('TLS Certificate'); | ||
const keyInput = getByLabelText('Private Key'); | ||
|
||
act(() => { | ||
userEvent.type(labelInput, 'my-cert-0'); | ||
userEvent.type(certInput, 'massive cert'); | ||
userEvent.type(keyInput, 'massive key'); | ||
|
||
userEvent.click(getByTestId('submit')); | ||
}); | ||
|
||
await waitFor(() => expect(onClose).toBeCalled()); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API spec has been updated to indicate that
certificate
will now be returned inGET /v4beta/aglb/{id}/certificates
.