Hint that a piped collection is unwrapped in single-value assertions#2806
Merged
Conversation
Piping a collection into Should-HaveType unwraps it - one item becomes a scalar, several become [object[]] - so the assertion no longer sees the original collection type and fails confusingly. Detect that on the failure path and hint to pass the value with -Actual instead. Also point the collection-on-Expected error at Should-BeCollection so the suggestion matches the new assertions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the heavily-wildcarded Verify-Like match with the exact hint text, and make the two unwrap cases (multi-item -> [Object[]], one-item -> scalar) explicit in the -ForEach data and test names. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The PipelineSource trick recovers the original piped collection's real type and item count, so the hint can be specific instead of generic: - a single-item collection is unwrapped to its one element, so the assertion sees a scalar (e.g. [string]); - a multi-item collection is streamed and re-collected into [Object[]]. A genuinely piped scalar keeps its type and still gets no hint, which the trick can tell apart from an unwrapped single-item collection. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ctions An empty piped collection (Count 0) sends no items, and a multi-item [Object[]] that is streamed and re-collected back into an [Object[]] never loses its type, so in both cases there is no unwrapping to explain. Guard these so the hint only fires when the pipeline genuinely changed the observable type. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The #2801 hint that explains how piping a collection unwraps it (one item becomes a scalar, several become [Object[]]) was only shown by Should-HaveType. The same surprise applies to every assertion that inspects a single value, so generalise it. - Add a Scalar variant to Get-AssertionGotcha. It tells the same unwrap story as ExactType but for assertions that care about the value rather than its type, so it has no "type did not change" guard -- an [Object[]] collapsed from a piped collection is still worth pointing out. - Wire the hint into the single-value and type assertions: Should-Be, Should-NotBe, Should-BeNull, Should-NotBeNull, Should-BeSame, Should-NotBeSame, Should-NotHaveType, Should-BeHashtable, the boolean assertions, and the string assertions that compare a whole value. - Comparison and time assertions (Should-BeGreaterThan and friends, Should-BeAfter, Should-BeBefore) threw a native conversion error when a piped multi-item collection was unwrapped to [Object[]]. Wrap the comparison so they now fail cleanly with the hint, while still rethrowing the original error for a genuine non-pipeline mismatch. - Add a dedicated Get-AssertionGotcha test file that drives every input shape through a fake unrolling assertion and a fake non-unrolling one, so the exact wording for all four variants lives in one place, plus an integration check that the real assertions wire the hint up. Converge the now-redundant exhaustive Should-HaveType wording tests to smoke tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mention the new hint both where the pipeline-unwrap behaviour is explained (Pipeline vs. -Actual) and in the richer-failure-messages list, with a short example of the hint a failing type assertion now shows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
3978ecd to
c534662
Compare
nohwnd
added a commit
to pester/docs
that referenced
this pull request
Jun 29, 2026
* Document the piped-collection assertion hint for v6 Add a "Piping vs. -Actual" subsection to the v5-to-v6 migration guide explaining that the new Should-* assertions take their actual value from the pipeline (which unwraps and re-collects collections as [object[]]) or from -Actual, and showing the failure-path hint that points users back to -Actual. Docs for pester/Pester#2806. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Note that the piped-collection hint is best-effort The pipeline can't reliably distinguish a single-item collection from a scalar, and a collection's original type isn't visible on the right-hand side of the pipeline. Pester recovers the piped value through tricks that work for common cases but not every one, so the hint won't always appear; recommend -Actual when the exact value or collection type matters. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Piping a collection into an assertion that inspects a single value unwraps the collection first — a one-item collection becomes its single element, several items become
[Object[]]— so the assertion never sees the collection you piped and fails with a confusing message. This started as aShould-HaveTypefix (#2801), but the same surprise applies to every single-value and type assertion, so this PR generalises the hint.On the failure path only, the assertion recovers the original piped value (via the
PipelineSourcetrick) and appends a hint that explains exactly what the pipeline did.A type assertion (
Should-HaveType,Should-NotHaveType):A single-value assertion (
Should-Be, booleans, strings, comparisons, …), here a one-item collection (@(1) | Should-Be 2):What's covered
Should-HaveType,Should-NotHaveType.Should-Be,Should-NotBe,Should-BeNull,Should-NotBeNull,Should-BeSame,Should-NotBeSame,Should-BeHashtable, the boolean assertions (Should-BeTrue,Should-BeFalse,Should-BeTruthy,Should-BeFalsy), and the string equality/emptiness assertions (Should-BeString,Should-BeEmptyString,Should-NotBeEmptyString,Should-NotBeWhiteSpaceString).Should-BeGreaterThan/…OrEqual,Should-BeLessThan/…OrEqual,Should-BeAfter,Should-BeBefore. These threw a native conversion error when a piped multi-item collection was unwrapped to[Object[]]; the comparison is now wrapped so they fail cleanly with the hint, while a genuine non-pipeline error is still rethrown unchanged.Notes
-Actualdoes not trigger it. For type assertions a piped[Object[]]that stays[Object[]]is not flagged — nothing was lost.-nestring assertions (Should-NotBeString,Should-BeLikeString,Should-NotBeLikeString,Should-MatchString,Should-NotMatchString) already reject a piped collection with their own collection-specific guidance, so they don't get this hint.Get-AssertionGotcha) and is covered shape-by-shape in a newGet-AssertionGotcha.Tests.ps1, which drives the gotcha through a fake unrolling assertion and a fake non-unrolling one, plus an integration check that the real assertions wire the hint up.Fix #2801