Skip to content
Closed
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ appWorkingDir | Optional working directory path for the application.
prerun | An object containing either `script` or `command` key. The value of each key must be a valid PowerShell script or command to be executed prior to the WinAppDriver session startup. See [Power Shell commands execution](#power-shell-commands-execution) for more details. Example: `{script: 'Get-Process outlook -ErrorAction SilentlyContinue'}`
postrun | An object containing either `script` or `command` key. The value of each key must be a valid PowerShell script or command to be executed after WinAppDriver session is stopped. See [Power Shell commands execution](#power-shell-commands-execution) for more details.
isolatedScriptExecution | Whether PowerShell scripts are executed in an isolated session. Default is `false`.
appEnvironment | Optional object of custom environment variables to inject into the PowerShell session. The variables are only available for the lifetime of the session and do not affect the system environment. Example: `{"MY_VAR": "hello", "API_URL": "http://localhost:3000"}`.

Please note that more capabilities will be added as the development of this driver progresses. Since it is still in its early stages, some features may be missing or subject to change. If you need a specific capability or encounter any issues, please feel free to open an issue.

Expand Down
16 changes: 14 additions & 2 deletions lib/commands/powershell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@ const NULL_ROOT_ELEMENT = /* ps1 */ `$rootElement = $null`;
const INIT_ELEMENT_TABLE = /* ps1 */ `$elementTable = New-Object System.Collections.Generic.Dictionary[[string]\`,[AutomationElement]]`;

export async function startPowerShellSession(this: NovaWindowsDriver): Promise<void> {
const powerShell = spawn('powershell.exe', ['-NoExit', '-Command', '-']);
const spawnEnv = this.caps.appEnvironment
? { ...process.env, ...(this.caps.appEnvironment as Record<string, string>) }
: process.env;

if (this.caps.appEnvironment) {
const keys = Object.keys(this.caps.appEnvironment as Record<string, string>);
this.log.info(`Applying appEnvironment variables to PowerShell session: ${keys.join(', ')}`);
}

const powerShell = spawn('powershell.exe', ['-NoExit', '-Command', '-'], { env: spawnEnv });
powerShell.stdout.setEncoding('utf8');
powerShell.stderr.setEncoding('utf8');

Expand Down Expand Up @@ -93,7 +102,10 @@ export async function startPowerShellSession(this: NovaWindowsDriver): Promise<v
export async function sendIsolatedPowerShellCommand(this: NovaWindowsDriver, command: string): Promise<string> {
const magicNumber = 0xF2EE;

const powerShell = spawn('powershell.exe', ['-NoExit', '-Command', '-']);
const spawnEnv = this.caps.appEnvironment
? { ...process.env, ...(this.caps.appEnvironment as Record<string, string>) }
: process.env;
const powerShell = spawn('powershell.exe', ['-NoExit', '-Command', '-'], { env: spawnEnv });
try {
powerShell.stdout.setEncoding('utf8');
powerShell.stdout.setEncoding('utf8');
Expand Down
3 changes: 3 additions & 0 deletions lib/constraints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export const UI_AUTOMATION_DRIVER_CONSTRAINTS = {
isolatedScriptExecution: {
isBoolean: true,
},
appEnvironment: {
isObject: true,
},
'ms:waitForAppLaunch': {
isNumber: true,
},
Expand Down
18 changes: 17 additions & 1 deletion test/e2e/session.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { existsSync, unlinkSync } from 'node:fs';
import { existsSync, readFileSync, unlinkSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { beforeEach, describe, expect, it } from 'vitest';
Expand Down Expand Up @@ -136,6 +136,22 @@ describe('Session creation and capabilities', () => {
if (existsSync(markerPath)) { unlinkSync(markerPath); }
});

it('passes appEnvironment variables into the PowerShell session', async () => {
const markerPath = join(tmpdir(), `novawindows-session-env-${Date.now()}.txt`);
const driver = await createRootSession({
'appium:appEnvironment': { NOVA_TEST_VAR: 'hello_from_env' },
'appium:prerun': {
script: `[System.IO.File]::WriteAllText('${markerPath}', $env:NOVA_TEST_VAR)`,
},
});
try {
expect(readFileSync(markerPath, 'utf8')).toBe('hello_from_env');
} finally {
await quitSession(driver);
if (existsSync(markerPath)) { unlinkSync(markerPath); }
}
});

it('throws when an unknown automationName is specified', async () => {
const { remote } = await import('webdriverio');
await expect(
Expand Down