|
8 | 8 | // Migrated from: |
9 | 9 | // x-pack/platform/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/general.ts |
10 | 10 | // |
11 | | -// 10 of 13 tests migrated. Skipped: |
12 | | -// - "should not be able to delete a preconfigured connector": requires preconfigured 'Serverlog' |
13 | | -// - "should not be able to edit a preconfigured connector": requires 'test-preconfigured-email' |
14 | | -// - "Execution log": requires test.always-firing via createRuleWithActionsAndParams |
| 11 | +// 13 of 13 tests migrated. |
15 | 12 |
|
16 | 13 | import { v4 as uuidv4 } from 'uuid'; |
17 | 14 | import type { KbnClient, ScoutPage } from '@kbn/scout'; |
@@ -441,6 +438,153 @@ test.describe('General connector functionality', { tag: tags.stateful.classic }, |
441 | 438 | await page.testSubj.click('euiFlyoutCloseButton'); |
442 | 439 | }); |
443 | 440 |
|
444 | | - // Skipped: requires test.always-firing rule type via createRuleWithActionsAndParams. |
445 | | - test.skip('Execution log - renders the event log list and can filter/sort', async () => {}); |
| 441 | + test('Execution log - renders the event log list and can filter/sort', async ({ |
| 442 | + browserAuth, |
| 443 | + page, |
| 444 | + kbnClient, |
| 445 | + pageObjects, |
| 446 | + }) => { |
| 447 | + await browserAuth.loginAsAdmin(); |
| 448 | + |
| 449 | + // Create an ES query rule that always executes (substitute for test.always-firing) |
| 450 | + const ruleName = `scout-exec-log-${Date.now()}`; |
| 451 | + const createResp = await kbnClient.request<{ id: string }>({ |
| 452 | + method: 'POST', |
| 453 | + path: '/api/alerting/rule', |
| 454 | + headers: { 'kbn-xsrf': 'scout' }, |
| 455 | + body: { |
| 456 | + name: ruleName, |
| 457 | + rule_type_id: '.es-query', |
| 458 | + consumer: 'stackAlerts', |
| 459 | + params: { |
| 460 | + searchType: 'esQuery', |
| 461 | + timeWindowSize: 5, |
| 462 | + timeWindowUnit: 'm', |
| 463 | + threshold: [0], |
| 464 | + thresholdComparator: '>=', |
| 465 | + size: 100, |
| 466 | + esQuery: '{"query":{"match_all":{}}}', |
| 467 | + aggType: 'count', |
| 468 | + groupBy: 'all', |
| 469 | + termSize: 5, |
| 470 | + excludeHitsFromPreviousRun: false, |
| 471 | + sourceFields: [], |
| 472 | + index: ['.kibana'], |
| 473 | + timeField: '@timestamp', |
| 474 | + }, |
| 475 | + schedule: { interval: '1m' }, |
| 476 | + tags: ['scout-exec-log'], |
| 477 | + actions: [], |
| 478 | + enabled: true, |
| 479 | + }, |
| 480 | + }); |
| 481 | + const ruleId = createResp.data.id; |
| 482 | + |
| 483 | + try { |
| 484 | + // Trigger an immediate run |
| 485 | + await kbnClient.request({ |
| 486 | + method: 'POST', |
| 487 | + path: `/internal/alerting/rule/${ruleId}/_run_soon`, |
| 488 | + headers: { 'kbn-xsrf': 'scout' }, |
| 489 | + }); |
| 490 | + |
| 491 | + // Poll execution log until at least 1 execution appears (max 30s) |
| 492 | + const dateStart = new Date(); |
| 493 | + const pollEnd = Date.now() + 30_000; |
| 494 | + let hasExecutions = false; |
| 495 | + while (!hasExecutions && Date.now() < pollEnd) { |
| 496 | + await page.waitForTimeout(1_000); |
| 497 | + try { |
| 498 | + const logResp = await kbnClient.request<{ total: number }>({ |
| 499 | + method: 'GET', |
| 500 | + path: `/internal/alerting/rule/${ruleId}/_execution_log`, |
| 501 | + headers: {}, |
| 502 | + query: { date_start: dateStart.toISOString() }, |
| 503 | + }); |
| 504 | + hasExecutions = logResp.data.total > 0; |
| 505 | + } catch { |
| 506 | + // keep polling |
| 507 | + } |
| 508 | + } |
| 509 | + |
| 510 | + // Navigate to rule details and click Logs tab |
| 511 | + await pageObjects.ruleDetailsPage.gotoById(ruleId); |
| 512 | + await page.testSubj.click('logsTab'); |
| 513 | + |
| 514 | + // Guard: if tabbed content is not present, the test cannot proceed (matches FTR guard) |
| 515 | + if ( |
| 516 | + !(await page.testSubj |
| 517 | + .locator('ruleDetailsTabbedContent') |
| 518 | + .isVisible({ timeout: 2_000 }) |
| 519 | + .catch(() => false)) |
| 520 | + ) { |
| 521 | + return; |
| 522 | + } |
| 523 | + |
| 524 | + // Allow entries to accumulate then refresh |
| 525 | + await page.waitForTimeout(5_000); |
| 526 | + await page.testSubj.click('superDatePickerApplyTimeButton'); |
| 527 | + |
| 528 | + // Event log list and status filter both exist |
| 529 | + await expect(page.testSubj.locator('eventLogList')).toBeVisible({ timeout: 10_000 }); |
| 530 | + await expect(page.testSubj.locator('eventLogStatusFilterButton')).toBeVisible(); |
| 531 | + |
| 532 | + // Status badge starts at 0 (no filters active) |
| 533 | + const statusBadge = page.testSubj |
| 534 | + .locator('eventLogStatusFilterButton') |
| 535 | + .locator('.euiNotificationBadge'); |
| 536 | + await expect(statusBadge).toHaveText('0'); |
| 537 | + |
| 538 | + // Enable "success" filter |
| 539 | + await page.testSubj.click('eventLogStatusFilterButton'); |
| 540 | + await page.testSubj.click('eventLogStatusFilter-success'); |
| 541 | + await page.testSubj.click('eventLogStatusFilterButton'); |
| 542 | + |
| 543 | + // Status badge now shows 1 active filter |
| 544 | + await expect(statusBadge).toHaveText('1'); |
| 545 | + |
| 546 | + // At least one data row exists |
| 547 | + await expect(page.locator('.euiDataGridRow')).not.toHaveCount(0, { timeout: 10_000 }); |
| 548 | + |
| 549 | + // Ensure timestamp column is visible |
| 550 | + await page.testSubj.click('dataGridColumnSelectorButton'); |
| 551 | + const colToggle = page.testSubj.locator( |
| 552 | + 'dataGridColumnSelectorToggleColumnVisibility-timestamp' |
| 553 | + ); |
| 554 | + if ((await colToggle.getAttribute('aria-checked')) === 'false') { |
| 555 | + await colToggle.click(); |
| 556 | + } |
| 557 | + await page.testSubj.click('dataGridColumnSelectorButton'); |
| 558 | + |
| 559 | + // At least one timestamp cell must contain a valid date |
| 560 | + const timestampCells = await page |
| 561 | + .locator('[data-gridcell-column-id="timestamp"][data-test-subj="dataGridRowCell"]') |
| 562 | + .all(); |
| 563 | + let validTimestamps = 0; |
| 564 | + for (const cell of timestampCells) { |
| 565 | + const text = await cell.innerText(); |
| 566 | + if (text.toLowerCase() !== 'invalid date' && !isNaN(Date.parse(text))) { |
| 567 | + validTimestamps++; |
| 568 | + } |
| 569 | + } |
| 570 | + expect(validTimestamps).toBeGreaterThan(0); |
| 571 | + |
| 572 | + // Sort ascending: open column action menu, click 2nd button (index 1 = ascending) |
| 573 | + await page.testSubj.locator('dataGridHeaderCell-timestamp').hover(); |
| 574 | + await page.testSubj.click('dataGridHeaderCellActionButton-timestamp'); |
| 575 | + await page.testSubj.locator('dataGridHeaderCellActionGroup-timestamp').waitFor(); |
| 576 | + await page.testSubj |
| 577 | + .locator('dataGridHeaderCellActionGroup-timestamp') |
| 578 | + .locator('li:nth-child(2) button') |
| 579 | + .click(); |
| 580 | + |
| 581 | + await expect(page.testSubj.locator('dataGridHeaderCellSortingIcon-timestamp')).toBeVisible(); |
| 582 | + } finally { |
| 583 | + await kbnClient.request({ |
| 584 | + method: 'DELETE', |
| 585 | + path: `/internal/alerting/rule/${ruleId}`, |
| 586 | + headers: { 'kbn-xsrf': 'scout' }, |
| 587 | + }); |
| 588 | + } |
| 589 | + }); |
446 | 590 | }); |
0 commit comments