feat(appium,base-driver,fake-driver,fake-plugin,test-support,types): updateServer receives cliArgs param
This PR passes a `cliArgs` parameter to the static method `updateServer` of drivers and plugins so they can take action on the server configuration based on the content of the arguments.
Note that `cliArgs` is a misnomer, because these args can also come from configuration files.
Closes
MODIFY
packages/appium/lib/main.js
packages/appium/lib/main.js
@@ -304,6 +304,7 @@ async function main(args) {
const serverUpdaters = getServerUpdaters(driverClasses, pluginClasses);
const extraMethodMap = getExtraMethodMap(driverClasses, pluginClasses);
+ /** @type {import('@appium/base-driver').ServerOpts} */
const serverOpts = {
routeConfiguringFunction,
port: parsedArgs.port,
@@ -312,6 +313,7 @@ async function main(args) {
basePath: parsedArgs.basePath,
serverUpdaters,
extraMethodMap,
+ cliArgs: parsedArgs,
};
if (parsedArgs.keepAliveTimeout) {
serverOpts.keepAliveTimeout = parsedArgs.keepAliveTimeout * 1000;

MODIFY
packages/appium/test/e2e/driver.e2e.spec.js
packages/appium/test/e2e/driver.e2e.spec.js
@@ -114,6 +114,14 @@ describe('FakeDriver - via HTTP', function () {
const {data} = await axios.get(`${testServerBaseUrl}/fakedriver`);
data.should.eql({fakedriver: 'fakeResponse'});
});
+ it('should update the server with cliArgs', async function () {
+ // we don't need to check the entire object, since it's large, but we can ensure an
+ // arg got through.
+ (await axios.post(`http://${TEST_HOST}:${port}/fakedriverCliArgs`)).data.should.have.property(
+ 'appiumHome',
+ appiumHome
+ );
+ });
});
describe('cli args handling for empty args', function () {

MODIFY
packages/appium/test/e2e/plugin.e2e.spec.js
packages/appium/test/e2e/plugin.e2e.spec.js
@@ -24,7 +24,7 @@ const wdOpts = {
capabilities: W3C_PREFIXED_CAPS,
};
const FAKE_DRIVER_DIR = path.join(PROJECT_ROOT, 'packages', 'fake-driver');
-const FAKE_PLUGIN_DIR = path.join(PROJECT_ROOT, 'node_modules', '@appium', 'fake-plugin');
+const FAKE_PLUGIN_DIR = path.join(PROJECT_ROOT, 'packages', 'fake-plugin');
describe('FakePlugin', function () {
/** @type {string} */
@@ -150,9 +150,11 @@ describe('FakePlugin', function () {
describe(`with plugin registered via type ${registrationType}`, function () {
/** @type {AppiumServer} */
let server;
+ /** @type {import('type-fest').LiteralUnion<'all', string>[]} */
+ let usePlugins;
before(async function () {
// then start server if we need to
- const usePlugins = registrationType === 'explicit' ? ['fake', 'p2', 'p3'] : ['all'];
+ usePlugins = registrationType === 'explicit' ? ['fake', 'p2', 'p3'] : ['all'];
const args = {
appiumHome,
port,
@@ -171,7 +173,12 @@ describe('FakePlugin', function () {
const res = {fake: 'fakeResponse'};
(await axios.post(`http://${TEST_HOST}:${port}/fake`)).data.should.eql(res);
});
-
+ it('should update the server with cliArgs', async function () {
+ const res = usePlugins;
+ // we don't need to check the entire object, since it's large, but we can ensure an
+ // arg got through.
+ (await axios.post(`http://${TEST_HOST}:${port}/cliArgs`)).data.usePlugins.should.eql(res);
+ });
it('should modify the method map with new commands', async function () {
const driver = await wdio(wdOpts);
const {sessionId} = driver;

MODIFY
packages/base-driver/lib/express/server.js
packages/base-driver/lib/express/server.js
@@ -40,6 +40,7 @@ async function server(opts) {
routeConfiguringFunction,
port,
hostname,
+ cliArgs,
allowCors = true,
basePath = DEFAULT_BASE_PATH,
extraMethodMap = {},
@@ -71,7 +72,7 @@ async function server(opts) {
});
// allow extensions to update the app and http server objects
for (const updater of serverUpdaters) {
- await updater(app, appiumServer);
+ await updater(app, appiumServer, cliArgs);
}
// once all configurations and updaters have been applied, make sure to set up a catchall
@@ -292,6 +293,7 @@ export {server, configureServer, normalizeBasePath};
* @typedef ServerOpts
* @property {RouteConfiguringFunction} routeConfiguringFunction
* @property {number} port
+ * @property {import('@appium/types').ServerArgs} cliArgs
* @property {string} [hostname]
* @property {boolean} [allowCors]
* @property {string} [basePath]

MODIFY
packages/base-driver/lib/index.js
packages/base-driver/lib/index.js
@@ -37,3 +37,7 @@ export {
// Web socket helpers
export {DEFAULT_WS_PATHNAME_PREFIX} from './express/websocket';
+
+/**
+ * @typedef {import('./express/server').ServerOpts} ServerOpts
+ */

MODIFY
packages/fake-driver/lib/driver.js
packages/fake-driver/lib/driver.js
@@ -117,9 +117,12 @@ class FakeDriver extends BaseDriver {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
- static async updateServer(expressApp /*, httpServer*/) {
+ static async updateServer(expressApp, httpServer, cliArgs) {
// eslint-disable-line require-await
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
+ expressApp.all('/fakedriverCliArgs', (req, res) => {
+ res.send(JSON.stringify(cliArgs));
+ });
}
}

MODIFY
packages/fake-plugin/lib/plugin.js
packages/fake-plugin/lib/plugin.js
@@ -40,9 +40,12 @@ class FakePlugin extends BasePlugin {
}
// eslint-disable-next-line no-unused-vars,require-await
- static async updateServer(expressApp, httpServer) {
+ static async updateServer(expressApp, httpServer, cliArgs) {
expressApp.all('/fake', FakePlugin.fakeRoute);
expressApp.all('/unexpected', FakePlugin.unexpectedData);
+ expressApp.all('/cliArgs', (req, res) => {
+ res.send(JSON.stringify(cliArgs));
+ });
}
async getPageSource(next, driver, ...args) {

MODIFY
packages/test-support/lib/driver-e2e-suite.js
packages/test-support/lib/driver-e2e-suite.js
@@ -136,6 +136,8 @@ export function driverE2ETestSuite(DriverClass, defaultCaps = {}) {
routeConfiguringFunction: routeConfiguringFunction(d),
port,
hostname: address,
+ // @ts-expect-error
+ cliArgs: {},
});
({startSession, getSession, endSession, newSessionURL, getCommand, postCommand} =
createSessionHelpers(port, address));

MODIFY
packages/types/lib/index.ts
packages/types/lib/index.ts
@@ -161,8 +161,10 @@ export type ExtensionType = DriverType | PluginType;
*
* @param expressApp - the Express 'app' object used by Appium for route handling
* @param httpServer - the node HTTP server that hosts the app
+ * @param cliArgs - Arguments from config files, CLI, etc.
*/
-export type UpdateServerCallback = (expressApp: Express, httpServer: AppiumServer) => Promise<void>;
+export type UpdateServerCallback = (expressApp: Express, httpServer: AppiumServer, cliArgs: ServerArgs) => Promise<void>;
+
/**
* Possible HTTP methods, as stolen from `axios`.

MODIFY
packages/types/lib/plugin.ts
packages/types/lib/plugin.ts
-import {MethodMap, UpdateServerCallback, Class, AppiumLogger} from '.';
+import {MethodMap, UpdateServerCallback, Class, AppiumLogger, PluginType} from '.';
import {Driver, ExternalDriver} from './driver';
/**

feat(appium,base-driver,fake-driver,fake-plugin,test-support,types): updateServer receives cliArgs param

This PR passes a `cliArgs` parameter to the static method `updateServer` of drivers and plugins so they can take action on the server configuration based on the content of the arguments.

Note that `cliArgs` is a misnomer, because these args can also come from configuration files.

Closes #17304