Skip to content
Open
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
7 changes: 5 additions & 2 deletions lib/BasePipelineSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,10 @@ export abstract class BasePipelineSolver<TInput> extends BaseSolver {
* Get the output from a specific pipeline stage
*/
getStageOutput<T = any>(stageOutput: string): T | undefined {
return this.pipelineOutputs[stageOutput]
if (!Object.hasOwn(this.pipelineOutputs, stageOutput)) {
return undefined
}
return this.pipelineOutputs[stageOutput] as T
}

/**
Expand All @@ -239,7 +242,7 @@ export abstract class BasePipelineSolver<TInput> extends BaseSolver {
* Check if a step has completed and produced output
*/
hasStageOutput(stageName: string): boolean {
return stageName in this.pipelineOutputs
return Object.hasOwn(this.pipelineOutputs, stageName)
}

/**
Expand Down
51 changes: 51 additions & 0 deletions tests/pipeline-output-lookup.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { expect, test } from "bun:test"
import { BasePipelineSolver } from "../lib/BasePipelineSolver"
import { BaseSolver } from "../lib/BaseSolver"

class EmptyPipeline extends BasePipelineSolver<Record<string, never>> {
pipelineDef = []
}

class ZeroOutputSolver extends BaseSolver {
override _step() {
this.solved = true
}

override getOutput() {
return 0
}
}

class ZeroOutputPipeline extends BasePipelineSolver<Record<string, never>> {
zeroSolver?: ZeroOutputSolver

pipelineDef = [
{
solverName: "zeroSolver",
solverClass: ZeroOutputSolver,
getConstructorParams: () => [],
},
]
}

for (const name of ["constructor", "toString", "__proto__"]) {
test(`no output exists for inherited Object property ${name}`, () => {
const pipeline = new EmptyPipeline({})
expect(Object.keys(pipeline.getAllOutputs())).toEqual([])
expect(pipeline.hasStageOutput(name)).toBe(false)
expect(pipeline.getStageOutput(name)).toBeUndefined()
})
}

test("missing ordinary stage names still report no output", () => {
const pipeline = new EmptyPipeline({})
expect(pipeline.hasStageOutput("zeroSolver")).toBe(false)
expect(pipeline.getStageOutput("zeroSolver")).toBeUndefined()
})

test("zero-valued completed outputs remain valid", () => {
const pipeline = new ZeroOutputPipeline({})
pipeline.solve()
expect(pipeline.hasStageOutput("zeroSolver")).toBe(true)
expect(pipeline.getStageOutput<number>("zeroSolver")).toEqual(0)
})
Loading