Skip to content

Commit

Permalink
✨ Setting to control Pester Working Directory (#118)
Browse files Browse the repository at this point in the history
Adds a setting to be able to specify the working directory of the Pester Test Runner
  • Loading branch information
JustinGrote authored Mar 29, 2022
1 parent b377566 commit c3cb336
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 24 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
"pester.pesterModulePath": {
"type": "string",
"markdownDescription": "This allows to specify a custom path to the Pester module. A relative path under the current project is allowed. If this is not set then Pester module is expected to be found in one of the paths specified by `$env:PSModulePath`."
},
"pester.workingDirectory": {
"type": "string",
"markdownDescription": "Specifies the working directory of the dedicated Pester Instance. While $PSScriptRoot is recommended when using relative paths in Pester Tests, the runner will also default to the path of the current first workspace folder. Specify this if you want a different working directory."
}
}
},
Expand Down
51 changes: 36 additions & 15 deletions src/pesterTestController.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { join, isAbsolute } from 'path'
import { existsSync } from 'fs'
import { join, isAbsolute, dirname } from 'path'
import {
debug as vscodeDebug,
DebugSession,
Expand Down Expand Up @@ -494,15 +493,28 @@ export class PesterTestController implements Disposable {
? (await this.powerShellExtensionClient!.GetVersionDetails()).exePath
: undefined

const cwd = this.getPesterWorkingDirectory()

// Restart PS to use the requested version if it is different from the current one
if (this.ps === undefined || this.ps.exePath !== exePath) {
log.info(`Starting PowerShell testing instance: ${exePath}`)
if (
this.ps === undefined ||
this.ps.exePath !== exePath ||
this.ps.cwd !== cwd
) {
if (this.ps !== undefined) {
log.warn(
`Detected PowerShell Session change from ${this.ps.exePath} to ${exePath}. Restarting Pester Runner.`
)
}
this.ps = new PowerShell(exePath)
const exePathDir = exePath
? dirname(exePath)
: '*DEFAULT POWERSHELL PATH*'
log.debug(
`Starting PowerShell Pester testing instance ${exePath} with working directory ${
cwd ? cwd : exePathDir
}`
)
this.ps = new PowerShell(exePath, cwd)
}

// Objects from the run will return to the success stream, which we then send to the return handler
Expand Down Expand Up @@ -543,6 +555,25 @@ export class PesterTestController implements Disposable {
await this.ps.run(script, psOutput, undefined, true, useNewProcess)
}
}
// Fetches the current working directory that Pester should use.
getPesterWorkingDirectory() {
const customCwd = workspace
.getConfiguration('pester')
.get<string>('workingDirectory')
if (customCwd) {
return customCwd
}

// TODO: Multi-root workspace support, for now this just looks for the first defined workspace
if (workspace.workspaceFolders && workspace.workspaceFolders.length > 1) {
log.warn(
'Multi-root workspace detected. Relative paths in Pester files will only work for the first workspace.'
)
}
return workspace.workspaceFolders
? workspace.workspaceFolders[0].uri.fsPath
: undefined
}

/** Fetches the current pester module path if a custom path was defined, otherwise returns undefined */
getPesterCustomModulePath() {
Expand Down Expand Up @@ -571,16 +602,6 @@ export class PesterTestController implements Disposable {
return resolvedPath
}

// Fetches the current working directory that Pester should use.
getPesterWorkingDirectory() {
const customCwd = workspace
.getConfiguration('pester')
.get<string>('workingDirectory')
if (customCwd) {
return customCwd
}
}

/** Returns a list of relative patterns based on user configuration for matching Pester files in the workspace */
getPesterRelativePatterns() {
const pesterFilePatterns = new Array<RelativePattern>()
Expand Down
18 changes: 9 additions & 9 deletions src/powershell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,14 @@ export function createSplitPSOutputStream(streams: IPSOutput) {
/** Represents an instance of a PowerShell process. By default this will use pwsh if installed, and will fall back to PowerShell on Windows,
* unless the exepath parameter is specified. Use the exePath parameter to specify specific powershell executables
* such as pwsh-preview or a pwsh executable not located in the PATH
* @param exePath The path to the powershell executable to use. If not specified, the default will be used.
* @param cwd The current working directory of the process. All paths will be relative to this. Defaults to the folder where pwsh.exe resides.
*/
export class PowerShell {
psProcess: ChildProcessWithoutNullStreams | undefined
private currentInvocation: Promise<any> | undefined
private currentInvocation: Promise<void> | undefined
private resolvedExePath: string | undefined
constructor(public exePath?: string) {}
constructor(public exePath?: string, public cwd?: string) {}

/** lazy-start a pwsh instance. If pwsh is not found but powershell is present, it will silently use that instead. */
private async initialize() {
Expand All @@ -169,13 +171,11 @@ export class PowerShell {
'pwsh not found in your path and you are not on Windows so PowerShell 5.1 is not an option. Did you install PowerShell first?'
)
}
this.psProcess = spawn(this.resolvedExePath, [
'-NoProfile',
'-NonInteractive',
'-NoExit',
'-Command',
'-'
])
this.psProcess = spawn(
this.resolvedExePath,
['-NoProfile', '-NonInteractive', '-NoExit', '-Command', '-'],
{ cwd: this.cwd }
)
// Warn if we have more than one listener set on a process
this.psProcess.stdout.setMaxListeners(1)
this.psProcess.stderr.setMaxListeners(1)
Expand Down

0 comments on commit c3cb336

Please sign in to comment.