Skip to content

Commit e0c6263

Browse files
lavocattMsarawan
authored andcommitted
[#175] e2e testing for the data plane
The test creates a restricted broker, waits for it to be ready, the uses the ConnectivityTester component to start a producer and consumer. Once they're status is a success the test deletes the broker and declares the success.
1 parent 1e23977 commit e0c6263

File tree

2 files changed

+174
-43
lines changed

2 files changed

+174
-43
lines changed

playwright/e2e/restricted-broker.spec.ts

Lines changed: 159 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,38 @@ test.describe('Restricted Broker End-to-End', () => {
155155
expect(brokerCertValue).toBe(`${brokerName}-broker-cert`);
156156
}).toPass({ timeout: 30000 });
157157

158-
// Step 4: Create the broker
158+
// Step 4: Enable data plane configuration
159+
const dataPlaneTab = page
160+
.locator('button, a')
161+
.filter({ hasText: /^Data plane$/i });
162+
await expect(dataPlaneTab).toBeVisible({ timeout: 10000 });
163+
await dataPlaneTab.click();
164+
165+
// Enable secured acceptor
166+
const acceptorSwitch = page.locator('input#restricted-acceptor-enabled');
167+
await expect(acceptorSwitch).toBeVisible({ timeout: 10000 });
168+
const acceptorLabel = page.locator(
169+
'label[for="restricted-acceptor-enabled"]',
170+
);
171+
await expect(acceptorLabel).toBeVisible({ timeout: 10000 });
172+
await acceptorLabel.click();
173+
await expect(acceptorSwitch).toBeChecked({ timeout: 10000 });
174+
175+
// Acknowledge JAAS secret management warning
176+
const consentCheckbox = page.locator('input#restricted-jaas-consent');
177+
await expect(consentCheckbox).toBeVisible({ timeout: 10000 });
178+
await consentCheckbox.scrollIntoViewIfNeeded();
179+
await consentCheckbox.check();
180+
181+
// Wait for data plane secrets to be ready
182+
await expect(page.locator('text=amqps-pem secret is ready.')).toBeVisible({
183+
timeout: 60000,
184+
});
185+
await expect(page.locator('text=JAAS BP secret is ready.')).toBeVisible({
186+
timeout: 60000,
187+
});
188+
189+
// Step 5: Create the broker
159190
const createButton = page
160191
.locator('button')
161192
.filter({ hasText: /^Create$/i })
@@ -175,7 +206,7 @@ test.describe('Restricted Broker End-to-End', () => {
175206
// Wait a moment for the broker to appear in the list
176207
await page.waitForTimeout(2000);
177208

178-
// Step 5: Wait for broker to be ready (stay on the list page)
209+
// Step 6: Wait for broker to be ready (stay on the list page)
179210
// The broker should show "5 ok / 5" in the Conditions column
180211
// Brokers can take 3-5 minutes to fully start up
181212
await expect(page.locator('text=/5\\s+ok\\s*\\/\\s*5/i')).toBeVisible({
@@ -184,49 +215,140 @@ test.describe('Restricted Broker End-to-End', () => {
184215

185216
console.log('✅ Broker is ready with 5 OK / 5 status');
186217

187-
// Step 6: Edit the broker to verify operator config fields are populated
188-
console.log('Testing broker edit page...');
189-
const brokerRow = page.locator(`tr:has-text("${brokerName}")`);
190-
await expect(brokerRow).toBeVisible({ timeout: 10000 });
218+
// Step 7: Go to broker details page
219+
console.log('Navigating to broker details...');
220+
const brokerLink = page
221+
.locator('a')
222+
.filter({ hasText: brokerName })
223+
.first();
224+
await expect(brokerLink).toBeVisible({ timeout: 10000 });
225+
await brokerLink.click();
226+
await page.waitForLoadState('domcontentloaded');
191227

192-
// Wait a moment for any UI updates to settle
193-
await page.waitForTimeout(2000);
228+
// Step 8: Open connectivity tester and create client cert + pemcfg
229+
console.log('Opening connectivity tester...');
230+
const openTesterButton = page.locator(
231+
'[data-test="open-connectivity-tester"]',
232+
);
233+
await expect(openTesterButton).toBeVisible({ timeout: 20000 });
234+
await openTesterButton.click();
194235

195-
// Find the kebab menu (actions menu) in the broker row
196-
console.log('Opening kebab menu for edit...');
197-
const kebabMenuForEdit = brokerRow.locator('button').last();
198-
await kebabMenuForEdit.scrollIntoViewIfNeeded();
199-
await kebabMenuForEdit.click({ timeout: 10000 });
236+
const connectivityModal = page.getByRole('dialog', {
237+
name: /Connectivity tester/i,
238+
});
239+
await expect(connectivityModal).toBeVisible({ timeout: 10000 });
240+
const connectivityWizard = connectivityModal.locator(
241+
'[data-test="connectivity-tester-wizard"]',
242+
);
243+
await expect(connectivityWizard).toBeVisible({ timeout: 10000 });
200244

201-
// Wait for dropdown menu to appear
202-
await page.waitForTimeout(1000);
245+
const issuerInput = connectivityWizard
246+
.locator(
247+
'input[placeholder="Select issuer"], input[aria-label="Type to filter"]',
248+
)
249+
.first();
250+
await expect(issuerInput).toBeVisible({ timeout: 10000 });
203251

204-
console.log('Clicking Edit broker option...');
205-
const editOption = page
206-
.locator('a, button')
207-
.filter({ hasText: /^Edit broker$/i });
208-
await expect(editOption).toBeVisible({ timeout: 10000 });
209-
await editOption.click();
252+
console.log('Selecting issuer and generating client cert...');
253+
await issuerInput.click();
254+
await issuerInput.fill('e2e-ca-issuer');
255+
await page.waitForTimeout(2000);
256+
const issuerOptionConnectivity = connectivityModal
257+
.locator('button:has-text("e2e-ca-issuer")')
258+
.first();
259+
await expect(issuerOptionConnectivity).toBeVisible({ timeout: 10000 });
260+
await issuerOptionConnectivity.click();
261+
262+
const generateClientCertButton = connectivityWizard.locator(
263+
'[data-test="connectivity-generate-client-cert"]',
264+
);
265+
await expect(generateClientCertButton).toBeEnabled({ timeout: 10000 });
266+
await generateClientCertButton.click();
210267

211-
// Wait for edit form to load
212-
await page.waitForLoadState('domcontentloaded');
213268
await expect(
214-
page.locator('label:has-text("Restricted mode")').first(),
215-
).toBeVisible({ timeout: 10000 });
269+
connectivityModal.locator(
270+
'text=messaging-client-cert certificate created.',
271+
),
272+
).toBeVisible({ timeout: 60000 });
273+
await expect(
274+
connectivityModal.locator('text=cert-pemcfg secret created.'),
275+
).toBeVisible({ timeout: 60000 });
276+
console.log('Client cert and pemcfg created.');
277+
278+
// Step 9: Move to broker endpoint step
279+
console.log('Advancing to broker endpoint step...');
280+
const nextButton = connectivityWizard.getByRole('button', {
281+
name: /^Next$/i,
282+
});
283+
await expect(nextButton).toBeEnabled({ timeout: 10000 });
284+
await nextButton.click();
216285

217-
// Verify that the Apply button is enabled
218-
// If operator config fields are not populated, form validation would fail
219-
// and the Apply button would be disabled
220-
console.log('Verifying Apply button is enabled (form is valid)...');
221-
const applyButton = page
222-
.locator('button')
223-
.filter({ hasText: /^Apply$/i })
224-
.first();
225-
await expect(applyButton).toBeEnabled({ timeout: 10000 });
286+
// Step 10: Move to run jobs step
287+
console.log('Advancing to run jobs step...');
288+
await expect(nextButton).toBeEnabled({ timeout: 10000 });
289+
await nextButton.click();
226290

227-
console.log(
228-
'✅ Apply button is enabled - operator config fields are properly populated!',
291+
// Run producer job and wait for success
292+
const runJobsStepButton = connectivityWizard.getByRole('button', {
293+
name: /^Run jobs$/i,
294+
});
295+
const runJobsRegion = connectivityWizard.locator(
296+
'[data-test="connectivity-run-jobs-step"]',
297+
);
298+
await runJobsStepButton.click();
299+
await expect(runJobsRegion).toBeVisible({ timeout: 10000 });
300+
301+
const producerGroup = runJobsRegion.locator(
302+
'[data-test="connectivity-producer"]',
303+
);
304+
const runProducerButton = runJobsRegion.locator(
305+
'[data-test="connectivity-run-producer"]',
306+
);
307+
await expect(runProducerButton).toBeEnabled({ timeout: 10000 });
308+
console.log('Running producer job...');
309+
await runProducerButton.click();
310+
await expect(producerGroup).toBeVisible({ timeout: 10000 });
311+
await expect
312+
.poll(async () => await producerGroup.innerText(), { timeout: 300000 })
313+
.toContain('Job status: succeeded');
314+
console.log('Producer job succeeded.');
315+
316+
// Run consumer job and wait for success
317+
const consumerGroup = runJobsRegion.locator(
318+
'[data-test="connectivity-consumer"]',
229319
);
320+
const runConsumerButton = runJobsRegion.locator(
321+
'[data-test="connectivity-run-consumer"]',
322+
);
323+
await expect(runConsumerButton).toBeEnabled({ timeout: 10000 });
324+
console.log('Running consumer job...');
325+
await runConsumerButton.click();
326+
await expect(consumerGroup).toBeVisible({ timeout: 10000 });
327+
await expect
328+
.poll(async () => await consumerGroup.innerText(), { timeout: 300000 })
329+
.toContain('Job status: succeeded');
330+
console.log('Consumer job succeeded.');
331+
332+
// Step 11: Cleanup resources
333+
console.log('Cleaning up connectivity test resources...');
334+
await expect(nextButton).toBeEnabled({ timeout: 10000 });
335+
await nextButton.click();
336+
const cleanupButton = connectivityWizard.getByRole('button', {
337+
name: /^Delete test resources$/i,
338+
});
339+
await expect(cleanupButton).toBeEnabled({ timeout: 10000 });
340+
await cleanupButton.click();
341+
await expect(
342+
connectivityWizard.locator('text=Connectivity test resources deleted.'),
343+
).toBeVisible({ timeout: 60000 });
344+
console.log('Connectivity test resources deleted.');
345+
346+
// Close the wizard
347+
console.log('Closing connectivity tester...');
348+
const cancelButton = connectivityWizard.getByRole('button', {
349+
name: /^Cancel$/i,
350+
});
351+
await cancelButton.click();
230352

231353
// Navigate back to broker list
232354
console.log('Returning to broker list...');
@@ -235,7 +357,7 @@ test.describe('Restricted Broker End-to-End', () => {
235357
});
236358
await page.waitForLoadState('domcontentloaded');
237359

238-
// Step 7: Delete the broker (from the list page)
360+
// Step 12: Delete the broker (from the list page)
239361
console.log(`Looking for broker row for deletion: ${brokerName}`);
240362
const brokerRowForDelete = page.locator(`tr:has-text("${brokerName}")`);
241363
await expect(brokerRowForDelete).toBeVisible({ timeout: 10000 });

src/brokers/broker-details/components/Overview/ConnectivityTester.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ export const ConnectivityTester: FC<ConnectivityTesterProps> = ({ cr }) => {
612612
name: t('Required secrets'),
613613
footer: { isNextDisabled: !hasClientCert },
614614
component: (
615-
<Form>
615+
<Form data-test="connectivity-required-secrets-step">
616616
<FormSection title={t('PEMCFG')}>
617617
{existingPemcfgSecret && pemcfgStatus?.status !== 'ready' && (
618618
<Alert
@@ -715,6 +715,7 @@ export const ConnectivityTester: FC<ConnectivityTesterProps> = ({ cr }) => {
715715
isDisabled={
716716
!selectedIssuer || clientCertStatus.status === 'working'
717717
}
718+
data-test="connectivity-generate-client-cert"
718719
>
719720
{clientCertStatus.status === 'working' && <Spinner size="sm" />}{' '}
720721
{t('Generate client certificate')}
@@ -727,7 +728,7 @@ export const ConnectivityTester: FC<ConnectivityTesterProps> = ({ cr }) => {
727728
name: t('Broker endpoint'),
728729
isDisabled: !hasClientCert,
729730
component: (
730-
<Form>
731+
<Form data-test="connectivity-broker-endpoint-step">
731732
<FormGroup label={t('Broker endpoint')} isRequired>
732733
<TextInput
733734
value={brokerEndpoint}
@@ -761,8 +762,8 @@ export const ConnectivityTester: FC<ConnectivityTesterProps> = ({ cr }) => {
761762
name: t('Run jobs'),
762763
isDisabled: !hasClientCert,
763764
component: (
764-
<Form>
765-
<FormSection title={t('Producer')}>
765+
<Form data-test="connectivity-run-jobs-step">
766+
<FormSection title={t('Producer')} data-test="connectivity-producer">
766767
<CodeBlock>
767768
<CodeBlockCode>{producerCommand}</CodeBlockCode>
768769
</CodeBlock>
@@ -799,12 +800,13 @@ export const ConnectivityTester: FC<ConnectivityTesterProps> = ({ cr }) => {
799800
variant={ButtonVariant.primary}
800801
onClick={handleRunProducer}
801802
isDisabled={producerStatus.status === 'working'}
803+
data-test="connectivity-run-producer"
802804
>
803805
{producerStatus.status === 'working' && <Spinner size="sm" />}{' '}
804806
{t('Run producer job')}
805807
</Button>
806808
</FormSection>
807-
<FormSection title={t('Consumer')}>
809+
<FormSection title={t('Consumer')} data-test="connectivity-consumer">
808810
<CodeBlock>
809811
<CodeBlockCode>{consumerCommand}</CodeBlockCode>
810812
</CodeBlock>
@@ -841,6 +843,7 @@ export const ConnectivityTester: FC<ConnectivityTesterProps> = ({ cr }) => {
841843
variant={ButtonVariant.primary}
842844
onClick={handleRunConsumer}
843845
isDisabled={consumerStatus.status === 'working'}
846+
data-test="connectivity-run-consumer"
844847
>
845848
{consumerStatus.status === 'working' && <Spinner size="sm" />}{' '}
846849
{t('Run consumer job')}
@@ -890,6 +893,7 @@ export const ConnectivityTester: FC<ConnectivityTesterProps> = ({ cr }) => {
890893
<Button
891894
variant={ButtonVariant.primary}
892895
onClick={() => setIsOpen(true)}
896+
data-test="open-connectivity-tester"
893897
>
894898
{t('Open connectivity tester')}
895899
</Button>
@@ -904,8 +908,13 @@ export const ConnectivityTester: FC<ConnectivityTesterProps> = ({ cr }) => {
904908
isOpen={isOpen}
905909
onClose={() => setIsOpen(false)}
906910
hasNoBodyWrapper
911+
data-test="connectivity-tester-modal"
907912
>
908-
<Wizard onClose={() => setIsOpen(false)} isVisitRequired>
913+
<Wizard
914+
onClose={() => setIsOpen(false)}
915+
isVisitRequired
916+
data-test="connectivity-tester-wizard"
917+
>
909918
{wizardSteps.map((step, index) => (
910919
<WizardStep
911920
key={step.name}

0 commit comments

Comments
 (0)