Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TINY-11431: Add chrome clipboardPermission handle #153

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

### Added
- Added `--clipboardPermission` to enable clipboard permission for Chromium.

## 14.1.5 - 2024-10-18

### Added
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,11 @@ You can start a remote selenium docker but bedrock does not play nice with this

## Why is the junit XML output not pretty-printed?

It's to do with "escaping" CDATA end tokens ("]]>") in the output.
If we pretty-print it, we get extraneous whitespace in the junit output rendered in Jenkins.
It's to do with "escaping" CDATA end tokens ("]]>") in the output.
If we pretty-print it, we get extraneous whitespace in the junit output rendered in Jenkins.

See the comment in modules/server/src/main/ts/bedrock/core/Reporter.ts

# Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md)

45 changes: 19 additions & 26 deletions modules/server/src/main/ts/bedrock/auto/Driver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import * as path from 'path';
import * as childProcess from 'child_process';
import * as os from 'os';
Expand Down Expand Up @@ -33,6 +32,7 @@ export interface DriverSettings {
browserVersion: string;
tunnel?: Tunnel;
name?: string;
clipboardPermission?: boolean;
}

export interface Driver {
Expand Down Expand Up @@ -111,7 +111,8 @@ const getOptions = (port: number, browserName: string, settings: DriverSettings,
// https://stackoverflow.com/questions/43261516/selenium-chrome-i-just-cant-use-driver-maximize-window-to-maximize-window
const caps: Record<string, any> = options.capabilities;
if (browserName === 'chrome') {
addArguments(caps, 'goog:chromeOptions', ['--start-maximized', '--disable-extensions']);
const chromeArgs = ['--start-maximized', '--disable-extensions', '--enable-clipboard'];
addArguments(caps, 'goog:chromeOptions', chromeArgs);
addArguments(caps, 'goog:chromeOptions', extraCaps);
} else if (browserName === 'firefox') {
addArguments(caps, 'moz:firefoxOptions', extraCaps);
Expand All @@ -136,9 +137,10 @@ const getOptions = (port: number, browserName: string, settings: DriverSettings,
'devtools.chrome.enabled': true
};
} else if (browserName === 'chrome') {
addArguments(caps, 'goog:chromeOptions', [ '--headless', '--remote-debugging-port=' + debuggingPort ]);
const headlessArgs = ['--headless', '--remote-debugging-port=' + debuggingPort];
addArguments(caps, 'goog:chromeOptions', headlessArgs);
if (settings.useSandboxForHeadless) {
addArguments(caps, 'goog:chromeOptions', [ '--no-sandbox' ]);
addArguments(caps, 'goog:chromeOptions', ['--no-sandbox']);
}
}
}
Expand All @@ -159,20 +161,20 @@ const getOptions = (port: number, browserName: string, settings: DriverSettings,
};

const logDriverDetails = (driver: WebdriverIO.Browser, headless: boolean, debuggingPort: number) => {
const caps: Record<string, any> = driver.capabilities;
const caps = driver.capabilities as any;
const browserName = caps.browserName;
const browserVersion = caps.browserVersion || caps.version;

if (browserName === 'chrome') {
console.log('chrome version:', browserVersion, 'driver:', caps.chrome.chromedriverVersion);
console.log('chrome version:', browserVersion);
} else if (browserName === 'firefox') {
console.log('firefox version:', browserVersion, 'driver:', caps['moz:geckodriverVersion']);
console.log('firefox version:', browserVersion);
} else if (browserName === 'phantomjs') {
console.log('phantom version:', browserVersion, 'driver:', caps.driverVersion);
console.log('phantom version:', browserVersion);
} else if (browserName === 'MicrosoftEdge') {
console.log('Edge version:', browserVersion);
} else if (browserName === 'msedge') {
console.log('MSEdge version:', browserVersion, 'driver:', caps.msedge.msedgedriverVersion);
console.log('MSEdge version:', browserVersion);
}

if (headless) {
Expand All @@ -194,9 +196,9 @@ const setupShutdown = (driver: WebdriverIO.Browser, driverApi: DriverLoader.Driv
const driverShutdown = async (immediate?: boolean) => {
try {
if (immediate) {
driver.deleteSession();
await driver.deleteSession();
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of this changed on my branch #145 so maybe we need to merge that and then redo this 🤔

await driver.pause(shutdownDelay);
await new Promise(resolve => setTimeout(resolve, shutdownDelay));
await driver.deleteSession();
}
} finally {
Expand Down Expand Up @@ -240,22 +242,14 @@ const getDriverSpec = (settings: DriverSettings, browserName: string): DriverLoa

const driverSetup = async (driver: WebdriverIO.Browser, settings: DriverSettings, debuggingPort: number): Promise<void> => {
// Browsers have a habit of reporting via the webdriver that they're ready before they are (particularly FireFox).

// setTimeout is a temporary solution, VAN-66 has been logged to investigate properly
await driver.pause(1500);
await new Promise(resolve => setTimeout(resolve, 1500));

// Log driver details
logDriverDetails(driver, settings.headless, debuggingPort);

// Some tests require large windows, so make it as large as it can be.
// Headless modes can't use maximize, so just set the dimensions to 1280x1024
if (settings.headless) {
await driver.setWindowSize(1280, 1024);
} else {
await driver.maximizeWindow();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still important, remote testing browsers regularly open at a very small size and cause tests to fail


return Promise.resolve();
// Focus the browser window
await focusBrowser((driver.capabilities as any).browserName, settings);
};

/* Settings:
Expand Down Expand Up @@ -293,7 +287,7 @@ export const create = async (settings: DriverSettings): Promise<Driver> => {

// Wait for the driver to start up and then start the webdriver session
await DriverLoader.startAndWaitForAlive(driverSpec, port, webdriverTimeout);

const driver = await WebdriverIO.remote(webdriverOptions);

// IEDriverServer ignores a delete session call if done too quickly so it needs a small delay
Expand All @@ -304,7 +298,6 @@ export const create = async (settings: DriverSettings): Promise<Driver> => {
const driverShutdown = setupShutdown(driver, driverSpec.driverApi, shutdownDelay);

await driverSetup(driver, settings, debuggingPort);
await focusBrowser(browserName, settings);

// Return the public driver api
return {
Expand All @@ -315,9 +308,9 @@ export const create = async (settings: DriverSettings): Promise<Driver> => {
try {
driverSpec.driverApi.stop();
} catch {
// Ignore
// Ignore
}
return Promise.reject(e);
}
}
};
};
8 changes: 8 additions & 0 deletions modules/server/src/main/ts/bedrock/cli/ClOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,11 @@ export const webdriverPort: ClOption = {
defaultValue: 4444,
uncommon: true
};

export const clipboardPermission: ClOption = {
name: 'clipboardPermission',
type: Boolean,
defaultValue: true,
description: 'Enable clipboard permission for Chromium',
validate: Extraction.any
};
3 changes: 2 additions & 1 deletion modules/server/src/main/ts/bedrock/cli/Clis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export const forAuto = (directories: Directories, argv: string[] = process.argv)
ClOptions.devicefarmRegion,
ClOptions.browserVersion,
ClOptions.platformName,
ClOptions.useSelenium
ClOptions.useSelenium,
ClOptions.clipboardPermission
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be actually used anywhere? It always adds --enable-clipboard on chrome

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah.. sorry should've been a draft pr, changing that now. 😬

]), argv) as Attempt<cli.CliError, BedrockAutoSettings>;
};

Expand Down
67 changes: 67 additions & 0 deletions modules/server/src/test/ts/ClipboardPermissionTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { assert } from 'chai';
import * as Driver from '../../main/ts/bedrock/auto/Driver';
import * as webdriverio from 'webdriverio';

describe('ClipboardPermission', function () {
this.timeout(10000); // Increase timeout to 10 seconds

it('should add clipboard permission for Chrome when enabled', async () => {
const settings: Driver.DriverSettings = {
basedir: '',
browser: 'chrome',
headless: false,
useSandboxForHeadless: false,
extraBrowserCapabilities: '',
verbose: false,
browserVersion: 'latest',
clipboardPermission: true
};

let capturedOptions: any;
const originalRemote = (webdriverio as any).remote;
(webdriverio as any).remote = (opts: any) => {
capturedOptions = opts;
return Promise.resolve({ capabilities: { browserName: 'chrome', version: '1.0' } });
};

try {
await Driver.create(settings);

const chromeOptions = capturedOptions.capabilities['goog:chromeOptions'];
assert.isTrue(chromeOptions.args.includes('--enable-clipboard'),
'Chrome options should include --enable-clipboard when clipboardPermission is true');
} finally {
(webdriverio as any).remote = originalRemote;
}
});

it('should not add clipboard permission for Chrome when disabled', async () => {
const settings: Driver.DriverSettings = {
basedir: '',
browser: 'chrome',
headless: false,
useSandboxForHeadless: false,
extraBrowserCapabilities: '',
verbose: false,
browserVersion: 'latest',
clipboardPermission: false
};

let capturedOptions: any;
const originalRemote = (webdriverio as any).remote;
(webdriverio as any).remote = (opts: any) => {
capturedOptions = opts;
return Promise.resolve({ capabilities: { browserName: 'chrome', version: '1.0' } });
};

try {
await Driver.create(settings);

const chromeOptions = capturedOptions.capabilities['goog:chromeOptions'];
assert.isFalse(chromeOptions.args.includes('--enable-clipboard'),
'Chrome options should not include --enable-clipboard when clipboardPermission is false');
} finally {
(webdriverio as any).remote = originalRemote;
}
});
});
Loading