diff --git a/src/plugins/console/public/application/containers/editor/monaco_editor_actions_provider.ts b/src/plugins/console/public/application/containers/editor/monaco_editor_actions_provider.ts index 8fe6a33332379..20c323f8e0ac1 100644 --- a/src/plugins/console/public/application/containers/editor/monaco_editor_actions_provider.ts +++ b/src/plugins/console/public/application/containers/editor/monaco_editor_actions_provider.ts @@ -132,12 +132,19 @@ export class MonacoEditorActionsProvider { visibility: 'hidden', }); } else { - // if a request is selected, the actions buttons are placed at lineNumberOffset - scrollOffset - const offset = this.editor.getTopForLineNumber(lineNumber) - this.editor.getScrollTop(); + const lineTop = this.editor.getTopForLineNumber(lineNumber); + const scrollTop = this.editor.getScrollTop(); + const offset = lineTop - scrollTop; + + // Ensure offset is never less than or equal to zero, moving it down + // by 1 px if needed. + const adjustedOffset = offset <= 0 ? 1 : offset; + this.setEditorActionsCss({ visibility: 'visible', - // Move position down by 1 px so that the action buttons panel doesn't cover the top border of the selected block - top: offset + 1, + // Move position down by 1 px so that the action buttons panel doesn't + // cover the top border of the selected block. + top: adjustedOffset + 1, }); } } diff --git a/test/functional/apps/console/_console.ts b/test/functional/apps/console/_console.ts index e53563542345d..160f08b3f34b3 100644 --- a/test/functional/apps/console/_console.ts +++ b/test/functional/apps/console/_console.ts @@ -224,6 +224,48 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); + it('should show actions menu when the first line of the request is not in the viewport', async () => { + await PageObjects.console.clearEditorText(); + await PageObjects.console.enterText(`PUT _ingest/pipeline/testme + { + "processors": [ + { + "inference": { + "model_id": "azure_openai_embeddings", + "input_output": { + "input_field": "body_content", + "output_field": "body_content_vector" + }, + "if": "ctx?.body_content!=null", + "ignore_failure": true, + "on_failure": [ + { + "append": { + "field": "_source._ingest.inference_errors", + "allow_duplicates": false, + "value": [ + { + "message": "...", + "pipeline": "ml-inference-search-edf-azureopenai-embeddings", + "timestamp": "{{{ _ingest.timestamp }}}" + } + ] + } + } + ] + } + } + ] + }`); + + // Reduce the height of the browser window so that the first line of the request is not in the viewport + await browser.setWindowSize(1300, 500); + expect(await PageObjects.console.isPlayButtonVisible()).to.be(true); + + // Reset it back to the original height + await browser.setWindowSize(1300, 1100); + }); + it('Shows OK when status code is 200 but body is empty', async () => { await PageObjects.console.clearEditorText(); diff --git a/test/functional/page_objects/console_page.ts b/test/functional/page_objects/console_page.ts index 71a4d05aecdb0..87308d24fd8c4 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -217,6 +217,10 @@ export class ConsolePageObject extends FtrService { await this.testSubjects.click('sendRequestButton'); } + public async isPlayButtonVisible() { + return await this.testSubjects.exists('sendRequestButton'); + } + public async clickCopyOutput() { await this.testSubjects.click('copyOutputButton'); }