Skip to content

Make Should-ContainCollection match a real sub-collection#2820

Merged
nohwnd merged 1 commit into
mainfrom
nohwnd-containcollection-research
Jun 30, 2026
Merged

Make Should-ContainCollection match a real sub-collection#2820
nohwnd merged 1 commit into
mainfrom
nohwnd-containcollection-research

Conversation

@nohwnd

@nohwnd nohwnd commented Jun 30, 2026

Copy link
Copy Markdown
Member

Problem

Should-ContainCollection / Should-NotContainCollection were implemented with PowerShell's -contains operator, which only tests whether a collection contains a single scalar value. When the right-hand side is itself a collection, -contains compares it by object identity and essentially never matches.

The comment-based help (which generates the pester.dev pages), and the assertion's name, told a different story — they documented multi-item examples and claimed they pass:

1, 2, 3 | Should-ContainCollection @(1, 2)   # help said "pass", actually FAILED
@(1)    | Should-ContainCollection @(1)       # help said "pass", actually FAILED

So the docs and the behaviour disagreed, and the promised sub-collection containment was never actually implemented. Should-NotContainCollection's help also had a copy-paste error referencing Should-ContainCollection in its examples.

Change

Implement true ordered-subsequence containment:

  • the expected items must appear in the actual collection in the same order,
  • gaps are allowed between matched items,
  • each actual item is consumed at most once, so repeated expected items need at least as many matching actual items,
  • a single value is still treated as a one-item collection, so existing single-item usage is unchanged.

The matching logic lives in a new shared Is-CollectionSubsequence helper (greedy two-pointer). The comment-based help for both assertions is rewritten to describe the real semantics, and the copy-paste error in Should-NotContainCollection is fixed.

Behaviour now

Expression Result
1, 2, 3 | Should-ContainCollection @(1, 2) ✅ pass (contiguous)
1, 2, 3 | Should-ContainCollection @(1, 3) ✅ pass (gap allowed)
1, 2, 3 | Should-ContainCollection @(3, 2, 1) ❌ fail (wrong order)
1, 2, 3 | Should-ContainCollection @(3, 4) ❌ fail (missing item)
1, 1, 2 | Should-ContainCollection @(1, 1) ✅ pass (two 1s available)
1, 2 | Should-ContainCollection @(1, 1) ❌ fail (no reuse)
@('a','b','c') | Should-ContainCollection 'b' ✅ pass (single value, unchanged)

Tests

Added contiguous, gapped, out-of-order and duplicate cases to both test files. All 868 assert tests pass, and PSScriptAnalyzer is clean on the changed files.

Note

This changes the runtime behaviour of these two assertions to match what their name and documentation always described. Single-item containment — the only thing that actually worked before — is preserved.

Should-ContainCollection and Should-NotContainCollection used PowerShell's
-contains operator, which only tests a single scalar value. The comment-based
help, however, documented multi-item examples such as
`1, 2, 3 | Should-ContainCollection @(1, 2)` and claimed they pass, when in
fact they failed at runtime. The name and docs promised sub-collection
containment that was never implemented.

Implement an ordered-subsequence match instead: the expected items must appear
in the actual collection in the same order, gaps are allowed, and each actual
item is consumed at most once (so repeated expected items need at least as many
matching actual items). A single value keeps the original one-item behaviour.

The matching lives in a shared Is-CollectionSubsequence helper. The
comment-based help for both assertions is rewritten to describe the real
semantics, and the copy-paste error in Should-NotContainCollection's examples
is fixed. Tests cover contiguous, gapped, out-of-order and duplicate cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nohwnd nohwnd merged commit 05db154 into main Jun 30, 2026
13 checks passed
@nohwnd nohwnd deleted the nohwnd-containcollection-research branch June 30, 2026 18:24
@nohwnd nohwnd mentioned this pull request Jun 30, 2026
nohwnd added a commit that referenced this pull request Jun 30, 2026
* Show real sub-collection matching in Should-ContainCollection release notes

Should-ContainCollection now matches an ordered sub-collection (gaps allowed)
as of #2820, but the 6.0.0 release notes still only showed the single-value
case. Update the example and the family table to describe the real behaviour.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Bump prerelease to rc4

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant