Skip to content

Commit e8caa06

Browse files
FTR: add chromium-based Edge browser support (elastic#61684) (elastic#63068)
* bump dependency, add edge support in ftr services * add config files * fix browser version for msedge * use npm ms-chromium-edge-driver * download edge driver aside from session creation * move dependency to dev * update dist/index file * bump edge-driver version * change type to msedge to match w3c spec * fix discover tests for Edge * Revert "fix discover tests for Edge" This reverts commit 87e7fdd. * bump driver version up Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent 9aa599c commit e8caa06

File tree

10 files changed

+412
-44
lines changed

10 files changed

+412
-44
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@
369369
"@types/recompose": "^0.30.6",
370370
"@types/redux-actions": "^2.6.1",
371371
"@types/request": "^2.48.2",
372-
"@types/selenium-webdriver": "^4.0.5",
372+
"@types/selenium-webdriver": "4.0.9",
373373
"@types/semver": "^5.5.0",
374374
"@types/sinon": "^7.0.13",
375375
"@types/strip-ansi": "^3.0.0",
@@ -454,6 +454,7 @@
454454
"load-grunt-config": "^3.0.1",
455455
"mocha": "^7.1.1",
456456
"mock-http-server": "1.3.0",
457+
"ms-chromium-edge-driver": "^0.2.0",
457458
"multistream": "^2.1.1",
458459
"murmurhash3js": "3.0.1",
459460
"mutation-observer": "^1.0.3",
@@ -472,7 +473,7 @@
472473
"react-textarea-autosize": "^7.1.2",
473474
"regenerate": "^1.4.0",
474475
"sass-lint": "^1.12.1",
475-
"selenium-webdriver": "^4.0.0-alpha.5",
476+
"selenium-webdriver": "^4.0.0-alpha.7",
476477
"simple-git": "1.116.0",
477478
"simplebar-react": "^2.1.0",
478479
"sinon": "^7.4.2",

packages/kbn-test/src/functional_test_runner/lib/config/schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export const schema = Joi.object()
136136
browser: Joi.object()
137137
.keys({
138138
type: Joi.string()
139-
.valid('chrome', 'firefox', 'ie')
139+
.valid('chrome', 'firefox', 'ie', 'msedge')
140140
.default('chrome'),
141141

142142
logPollingMs: Joi.number().default(100),

test/functional/config.edge.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
export default async function({ readConfigFile }) {
21+
const defaultConfig = await readConfigFile(require.resolve('./config'));
22+
23+
return {
24+
...defaultConfig.getAll(),
25+
26+
browser: {
27+
type: 'msedge',
28+
},
29+
30+
junit: {
31+
reportName: 'MS Chromium Edge UI Functional Tests',
32+
},
33+
};
34+
}

test/functional/services/browser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
5353
*/
5454
public readonly browserType: string = browserType;
5555

56-
public readonly isChrome: boolean = browserType === Browsers.Chrome;
56+
public readonly isChromium: boolean = [Browsers.Chrome, Browsers.ChromiumEdge].includes(
57+
browserType
58+
);
5759

5860
public readonly isFirefox: boolean = browserType === Browsers.Firefox;
5961

test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export class WebElementWrapper {
5555
private driver: WebDriver = this.webDriver.driver;
5656
private Keys = Key;
5757
public isW3CEnabled: boolean = (this.webDriver.driver as any).executor_.w3c === true;
58+
public isChromium: boolean = [Browsers.Chrome, Browsers.ChromiumEdge].includes(this.browserType);
5859

5960
public static create(
6061
webElement: WebElement | WebElementWrapper,
@@ -63,7 +64,7 @@ export class WebElementWrapper {
6364
timeout: number,
6465
fixedHeaderHeight: number,
6566
logger: ToolingLog,
66-
browserType: string
67+
browserType: Browsers
6768
): WebElementWrapper {
6869
if (webElement instanceof WebElementWrapper) {
6970
return webElement;
@@ -87,7 +88,7 @@ export class WebElementWrapper {
8788
private timeout: number,
8889
private fixedHeaderHeight: number,
8990
private logger: ToolingLog,
90-
private browserType: string
91+
private browserType: Browsers
9192
) {}
9293

9394
private async _findWithCustomTimeout(
@@ -243,7 +244,7 @@ export class WebElementWrapper {
243244
return this.clearValueWithKeyboard();
244245
}
245246
await this.retryCall(async function clearValue(wrapper) {
246-
if (wrapper.browserType === Browsers.Chrome || options.withJS) {
247+
if (wrapper.isChromium || options.withJS) {
247248
// https://bugs.chromium.org/p/chromedriver/issues/detail?id=2702
248249
await wrapper.driver.executeScript(`arguments[0].value=''`, wrapper._webElement);
249250
} else {
@@ -275,7 +276,7 @@ export class WebElementWrapper {
275276
await delay(100);
276277
}
277278
} else {
278-
if (this.browserType === Browsers.Chrome) {
279+
if (this.isChromium) {
279280
// https://bugs.chromium.org/p/chromedriver/issues/detail?id=30
280281
await this.retryCall(async function clearValueWithKeyboard(wrapper) {
281282
await wrapper.driver.executeScript(`arguments[0].select();`, wrapper._webElement);

test/functional/services/remote/browsers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ export enum Browsers {
2121
Chrome = 'chrome',
2222
Firefox = 'firefox',
2323
InternetExplorer = 'ie',
24+
ChromiumEdge = 'msedge',
2425
}

test/functional/services/remote/remote.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,23 @@ export async function RemoteProvider({ getService }: FtrProviderContext) {
4444
lifecycle,
4545
config.get('browser.logPollingMs')
4646
);
47+
4748
const isW3CEnabled = (driver as any).executor_.w3c;
4849

4950
const caps = await driver.getCapabilities();
50-
const browserVersion = caps.get(isW3CEnabled ? 'browserVersion' : 'version');
51+
const browserVersion = caps.get(
52+
isW3CEnabled || browserType === Browsers.ChromiumEdge ? 'browserVersion' : 'version'
53+
);
5154

52-
log.info(`Remote initialized: ${caps.get('browserName')} ${browserVersion}`);
55+
log.info(
56+
`Remote initialized: ${caps.get(
57+
'browserName'
58+
)} ${browserVersion}, w3c compliance=${isW3CEnabled}`
59+
);
5360

54-
if (browserType === Browsers.Chrome) {
61+
if ([Browsers.Chrome, Browsers.ChromiumEdge].includes(browserType)) {
5562
log.info(
56-
`Chromedriver version: ${caps.get('chrome').chromedriverVersion}, w3c=${isW3CEnabled}`
63+
`${browserType}driver version: ${caps.get(browserType)[`${browserType}driverVersion`]}`
5764
);
5865
}
5966

test/functional/services/remote/webdriver.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ import firefox from 'selenium-webdriver/firefox';
3333
// @ts-ignore types not available
3434
import ie from 'selenium-webdriver/ie';
3535
// @ts-ignore internal modules are not typed
36+
import edge from 'selenium-webdriver/edge';
37+
import { installDriver } from 'ms-chromium-edge-driver';
38+
// @ts-ignore internal modules are not typed
3639
import { Executor } from 'selenium-webdriver/lib/http';
3740
// @ts-ignore internal modules are not typed
3841
import { getLogger } from 'selenium-webdriver/lib/logging';
39-
4042
import { pollForLogEntry$ } from './poll_for_log_entry';
4143
import { createStdoutSocket } from './create_stdout_stream';
4244
import { preventParallelCalls } from './prevent_parallel_calls';
@@ -65,6 +67,7 @@ Executor.prototype.execute = preventParallelCalls(
6567
);
6668

6769
let attemptCounter = 0;
70+
let edgePaths: { driverPath: string | undefined; browserPath: string | undefined };
6871
async function attemptToCreateCommand(
6972
log: ToolingLog,
7073
browserType: Browsers,
@@ -76,6 +79,41 @@ async function attemptToCreateCommand(
7679

7780
const buildDriverInstance = async () => {
7881
switch (browserType) {
82+
case 'msedge': {
83+
if (edgePaths && edgePaths.browserPath && edgePaths.driverPath) {
84+
const edgeOptions = new edge.Options();
85+
if (headlessBrowser === '1') {
86+
// @ts-ignore internal modules are not typed
87+
edgeOptions.headless();
88+
}
89+
// @ts-ignore internal modules are not typed
90+
edgeOptions.setEdgeChromium(true);
91+
// @ts-ignore internal modules are not typed
92+
edgeOptions.setBinaryPath(edgePaths.browserPath);
93+
const session = await new Builder()
94+
.forBrowser('MicrosoftEdge')
95+
.setEdgeOptions(edgeOptions)
96+
.setEdgeService(new edge.ServiceBuilder(edgePaths.driverPath))
97+
.build();
98+
return {
99+
session,
100+
consoleLog$: pollForLogEntry$(session, logging.Type.BROWSER, logPollingMs).pipe(
101+
takeUntil(lifecycle.cleanup.after$),
102+
map(({ message, level: { name: level } }) => ({
103+
message: message.replace(/\\n/g, '\n'),
104+
level,
105+
}))
106+
),
107+
};
108+
} else {
109+
throw new Error(
110+
`Chromium Edge session requires browser or driver path to be defined: ${JSON.stringify(
111+
edgePaths
112+
)}`
113+
);
114+
}
115+
}
116+
79117
case 'chrome': {
80118
const chromeCapabilities = Capabilities.chrome();
81119
const chromeOptions = [
@@ -262,6 +300,11 @@ export async function initWebDriver(
262300
log.verbose(entry.message);
263301
});
264302

303+
// download Edge driver only in case of usage
304+
if (browserType === Browsers.ChromiumEdge) {
305+
edgePaths = await installDriver();
306+
}
307+
265308
return await Promise.race([
266309
(async () => {
267310
await delay(2 * MINUTE);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
export default async function({ readConfigFile }) {
8+
const chromeConfig = await readConfigFile(require.resolve('./config'));
9+
10+
return {
11+
...chromeConfig.getAll(),
12+
13+
browser: {
14+
type: 'msedge',
15+
},
16+
17+
junit: {
18+
reportName: 'MS Chromium Edge XPack UI Functional Tests',
19+
},
20+
};
21+
}

0 commit comments

Comments
 (0)