Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ export class ServiceMapPage {
public serviceMapFocusMapButton: Locator;
public serviceMapDependencyDetailsButton: Locator;
public serviceMapEdgeExploreTracesButton: Locator;
public serviceMapOptionsPanel: Locator;
public serviceMapFindInPageInput: Locator;
/**
* Native search `<input>` (`SERVICE_MAP_FIND_INPUT_ID`). Prefer this for fill/focus so React
* `onFocus` runs and find highlights sync (`service_map_find_in_page` gates on `isFocused`).
*/
public serviceMapFindInPageNativeInput: Locator;
public serviceMapFindMatchSummary: Locator;

constructor(private readonly page: ScoutPage, private readonly kbnUrl: KibanaUrl) {
this.serviceMap = page.testSubj.locator('serviceMap');
Expand All @@ -52,6 +60,10 @@ export class ServiceMapPage {
this.serviceMapEdgeExploreTracesButton = page.testSubj.locator(
'apmEdgeContentsOpenInDiscoverButton'
);
this.serviceMapOptionsPanel = page.testSubj.locator('serviceMapOptionsPanel');
this.serviceMapFindInPageInput = page.testSubj.locator('serviceMapControlsSearch');
this.serviceMapFindInPageNativeInput = page.locator('#serviceMapFindInPageInput');
this.serviceMapFindMatchSummary = page.testSubj.locator('serviceMapFindMatchSummary');
}

async gotoWithDateSelected(start: string, end: string, options?: { kuery?: string }) {
Expand Down Expand Up @@ -95,6 +107,23 @@ export class ServiceMapPage {
await this.serviceMapGraph.waitFor({ state: 'visible' });
}

/**
* Blur focused controls and move focus to `document.body` so the service map Ctrl/Cmd+K handler
* treats the shortcut as in scope (see graph.tsx).
*/
async focusBodyForMapShortcuts() {
await this.page.evaluate(() => {
(document.activeElement as HTMLElement | null)?.blur?.();
document.body.focus();
});
}

/** Triggers find-in-page focus via the same shortcut as the in-app hint (Control+K / Meta+K). */
async openFindInPageWithKeyboardShortcut() {
await this.focusBodyForMapShortcuts();
await this.page.keyboard.press('Control+KeyK');
}

async clickZoom(direction: 'in' | 'out') {
const button = direction === 'in' ? this.zoomInBtn : this.zoomOutBtn;
await button.waitFor({ state: 'visible' });
Expand Down Expand Up @@ -183,6 +212,15 @@ export class ServiceMapPage {
return this.serviceMapGraph.getByTestId(`serviceMapNode-service-${serviceName}`);
}

/**
* Highlight frame around the active find-in-page match (`HighlightWrapper` when `isActiveSearchMatch`).
*/
getActiveFindMatchHighlightFrame(serviceName: string) {
return this.getServiceNodeRoot(serviceName).locator(
'xpath=ancestor::*[@data-test-subj="serviceMapNodeSearchHighlightFrame"][1]'
);
}

/**
* The clickable/focusable service circle only. Prefer this over role+name: when shown, violated/degrading SLO
* badges can also be buttons whose accessible name includes the service name, so `getByRole('button', { name })`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,26 @@ test.describe(
await expect(node).toBeFocused();
});

await test.step('find-in-page: highlight frame while focused, Enter centers match', async () => {
await serviceMapPage.focusBodyForMapShortcuts();
await serviceMapPage.openFindInPageWithKeyboardShortcut();
// Fill the real input (#serviceMapFindInPageInput) so EuiFieldSearch onFocus runs and
// highlight context updates (filling by layout test-subj alone can leave isFocused false).
await serviceMapPage.serviceMapFindInPageNativeInput.fill(SERVICE_OPBEANS_JAVA);
await expect(serviceMapPage.serviceMapFindMatchSummary).toHaveText(/[1-9]/);

// Highlights are driven only while the find field is focused; centering the map after Enter
// can move focus and clear highlights, so assert the frame before Enter.
const highlightFrame =
serviceMapPage.getActiveFindMatchHighlightFrame(SERVICE_OPBEANS_JAVA);
await expect(highlightFrame).toBeVisible();
await expect(highlightFrame).toHaveAttribute('data-search-active-match');

await serviceMapPage.serviceMapFindInPageNativeInput.press('Enter');
await serviceMapPage.settleServiceMapLayout();
await expect(serviceMapPage.serviceMapFindMatchSummary).toHaveText(/[1-9]/);
});

await test.step('zoom controls are keyboard accessible', async () => {
await serviceMapPage.clickFitView();
await expect(serviceMapPage.zoomInBtnControl).toBeVisible();
Expand Down
Loading