Skip to content
Merged
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
3 changes: 2 additions & 1 deletion .buildkite/scripts/steps/functional/scout_ui_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ run_tests() {

EXIT_CODE=0

# Discovery Enhanced
# Discovery Enhanced && Maps
for run_mode in "--stateful"; do
run_tests "Discovery Enhanced: Parallel Workers" "x-pack/platform/plugins/private/discover_enhanced/ui_tests/parallel.playwright.config.ts" "$run_mode"
run_tests "Discovery Enhanced" "x-pack/platform/plugins/private/discover_enhanced/ui_tests/playwright.config.ts" "$run_mode"
run_tests "Maps" "x-pack/platform/plugins/shared/maps/ui_tests/playwright.config.ts" "$run_mode"
done

exit $EXIT_CODE
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ describe('createPlaywrightConfig', () => {
serversConfigDir: SCOUT_SERVERS_ROOT,
[VALID_CONFIG_MARKER]: true,
screenshot: 'only-on-failure',
testIdAttribute: 'data-test-subj',
trace: 'on-first-retry',
});
expect(config.globalSetup).toBeUndefined();
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-scout/src/playwright/config/create_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export function createPlaywrightConfig(options: ScoutPlaywrightOptions): Playwri
],
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
testIdAttribute: 'data-test-subj',
serversConfigDir: SCOUT_SERVERS_ROOT,
[VALID_CONFIG_MARKER]: true,
/* Base URL to use in actions like `await page.goto('/')`. */
Expand Down
6 changes: 6 additions & 0 deletions packages/kbn-scout/src/playwright/page_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ import { DashboardApp } from './dashboard_app';
import { DatePicker } from './date_picker';
import { DiscoverApp } from './discover_app';
import { FilterBar } from './fiter_bar';
import { MapsPage } from './maps_page';
import { RenderablePage } from './renderable_page';
import { createLazyPageObject } from './utils';

export interface PageObjects {
datePicker: DatePicker;
discover: DiscoverApp;
dashboard: DashboardApp;
filterBar: FilterBar;
maps: MapsPage;
renderable: RenderablePage;
}

/**
Expand All @@ -33,6 +37,8 @@ export function createCorePageObjects(page: ScoutPage): PageObjects {
dashboard: createLazyPageObject(DashboardApp, page),
discover: createLazyPageObject(DiscoverApp, page),
filterBar: createLazyPageObject(FilterBar, page),
maps: createLazyPageObject(MapsPage, page),
renderable: createLazyPageObject(RenderablePage, page),
// Add new page objects here
};
}
18 changes: 18 additions & 0 deletions packages/kbn-scout/src/playwright/page_objects/maps_page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { ScoutPage } from '..';

export class MapsPage {
constructor(private readonly page: ScoutPage) {}

async gotoNewMap() {
await this.page.gotoApp('maps/map');
}
}
43 changes: 43 additions & 0 deletions packages/kbn-scout/src/playwright/page_objects/renderable_page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { ScoutPage, expect } from '..';

export class RenderablePage {
constructor(private readonly page: ScoutPage) {}

async waitForRender(count: number = 1): Promise<void> {
await expect(async () => await renderWait(count, this.page)).toPass({
timeout: 10_000,
});
}
}

const RENDER_COMPLETE_SELECTOR = '[data-render-complete="true"]';
const RENDER_COMPLETE_PENDING_SELECTOR = '[data-render-complete="false"]';
const DATA_LOADING_SELECTOR = '[data-loading]';

async function renderWait(count: number, page: ScoutPage) {
const renderCompleteLocator = page.locator(RENDER_COMPLETE_SELECTOR);
const renderPendingDataTitleLocator = page
.locator(RENDER_COMPLETE_PENDING_SELECTOR)
.and(page.locator('data-title'));
const loadingLocator = page.locator(DATA_LOADING_SELECTOR);

await renderCompleteLocator.waitFor({ timeout: 1000 });
const completedElementsCount = await renderCompleteLocator.count();

if (completedElementsCount < count)
throw new Error(
`${completedElementsCount} elements completed rendering, still waiting on a total of ${count} - ${await renderPendingDataTitleLocator.all()}`
);

const loadingCount = await loadingLocator.count();
if (loadingCount > 0) throw new Error(`${loadingCount} elements still loading contents`);
}
8 changes: 4 additions & 4 deletions packages/kbn-scout/src/playwright/page_objects/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import { ScoutPage } from '../../fixtures';
* in certain test scenarios.
*
* @param PageObjectClass - The page object class to be instantiated lazily.
* @param scoutPage - ScoutPage instance, that extendes the Playwright `page` fixture and passed to the page object class constructor.
* @param scoutPage - ScoutPage instance, that extends the Playwright `page` fixture and passed to the page object class constructor.
* @param constructorArgs - Additional arguments to be passed to the page object class constructor.
* @returns A proxy object that behaves like an instance of the page object class, instantiating it on demand.
*/
export function createLazyPageObject<T extends object>(
PageObjectClass: new (page: ScoutPage, ...args: any[]) => T,
export function createLazyPageObject<T extends object, Args extends any[]>(
PageObjectClass: new (page: ScoutPage, ...args: Args) => T,
scoutPage: ScoutPage,
...constructorArgs: any[]
...constructorArgs: Args
): T {
let instance: T | null = null;
return new Proxy({} as T, {
Expand Down
2 changes: 1 addition & 1 deletion packages/kbn-scout/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@
"@kbn/mock-idp-utils",
"@kbn/test-subj-selector",
"@kbn/scout-info",
"@kbn/scout-reporting"
"@kbn/scout-reporting",
]
}
4 changes: 3 additions & 1 deletion x-pack/platform/plugins/shared/maps/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"public/**/*",
"server/**/*",
"server/config.ts",
"../../../../../typings/**/*"
"../../../../../typings/**/*",
"ui_tests/**/*",
],
"kbn_references": [
"@kbn/core",
Expand Down Expand Up @@ -92,6 +93,7 @@
"@kbn/field-utils",
"@kbn/react-hooks",
"@kbn/react-kibana-mount",
"@kbn/scout",
],
"exclude": [
"target/**/*",
Expand Down
22 changes: 22 additions & 0 deletions x-pack/platform/plugins/shared/maps/ui_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## How to run tests

You can drop the following in your terminal.

```bash
run_tests() {
local suit_name=$1
local config_path=$2
local run_mode=$3

echo "--- $suit_name ($run_mode) UI Tests"
if ! node scripts/scout run-tests "$run_mode" --config "$config_path"; then
echo "$suit_name: failed"
else
echo "$suit_name: passed"
fi
}

for run_mode in "--stateful" "--serverless=es" "--serverless=oblt" "--serverless=security"; do
run_tests "Maps" "x-pack/platform/plugins/shared/maps/ui_tests/playwright.config.ts" "$run_mode"
done
```
11 changes: 11 additions & 0 deletions x-pack/platform/plugins/shared/maps/ui_tests/fixtures/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export const VISIBLE_CHROME = 'kbnAppWrapper visibleChrome';
export const HIDDEN_CHROME = 'kbnAppWrapper hiddenChrome';
export const FULL_SCREEN_MODE = 'mapsFullScreenMode';
export const EXIT_FULL_SCREEN = 'exitFullScreenModeButton';
13 changes: 13 additions & 0 deletions x-pack/platform/plugins/shared/maps/ui_tests/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { createPlaywrightConfig } from '@kbn/scout';

// eslint-disable-next-line import/no-default-export
export default createPlaywrightConfig({
testDir: './tests',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { expect, tags, test } from '@kbn/scout';
import {
VISIBLE_CHROME,
HIDDEN_CHROME,
FULL_SCREEN_MODE,
EXIT_FULL_SCREEN,
} from '../fixtures/constants';

test.describe(
'Maps',
{
tag: tags.DEPLOYMENT_AGNOSTIC,
},
() => {
test.beforeEach(async ({ browserAuth, pageObjects }) => {
await browserAuth.loginAsViewer();
await pageObjects.maps.gotoNewMap();
await pageObjects.renderable.waitForRender();
});

test('Full screen mode', async ({ page }) => {
const fullScreenBtn = page.getByTestId(FULL_SCREEN_MODE);
const exitFullScreenBtn = page.getByTestId(EXIT_FULL_SCREEN);
const visibleChrome = page.getByTestId(VISIBLE_CHROME);
const hiddenChrome = page.getByTestId(HIDDEN_CHROME);
const baseMapBtn = page.getByRole('button', { name: 'Basemap' });

await expect(fullScreenBtn).toBeVisible();
await expect(exitFullScreenBtn).not.toBeVisible();
await expect(visibleChrome).toBeVisible();
await expect(hiddenChrome).not.toBeVisible();
await expect(baseMapBtn).toBeVisible();

await fullScreenBtn.click();

await expect(fullScreenBtn).not.toBeVisible();
await expect(exitFullScreenBtn).toBeVisible();
await expect(visibleChrome).not.toBeVisible();
await expect(hiddenChrome).toBeVisible();
await expect(baseMapBtn).toBeVisible();

await exitFullScreenBtn.click();

await expect(fullScreenBtn).toBeVisible();
});
}
);