The -contains operator is not a string operator, but a collection containment operator:
'a','b','c' -contains 'b' # correct use of -contains against collection
From the about_Comparison_Operators help topic:
Type         Operator      Description
Containment  -contains     Returns true when reference value contained in a collection
             -notcontains  Returns true when reference value not contained in a collection
             -in           Returns true when test value contained in a collection
             -notin        Returns true when test value not contained in a collection
Usually you would use the -like string operator in PowerShell, which supports Windows-style wildcard matching (* for any number of any characters, ? for exactly one of any character, [abcdef] for one of a character set):
'abc' -like '*b*' # $true
'abc' -like 'a*' # $true
Another alternative is the -match operator:
'abc' -match 'b' # $true
'abc' -match '^a' # $true
For verbatim substring matching, you would want to escape any input pattern, since -match is a regex operator:
'abc.e' -match [regex]::Escape('c.e')
An alternative is to use the String.Contains() method:
'abc'.Contains('b') # $true
With the caveat that, unlike powershell string operators, it's case-sensitive.
String.IndexOf() is yet another alternative, this one allows you to override the default case-sensitivity:
'ABC'.IndexOf('b', [System.StringComparison]::InvariantCultureIgnoreCase) -ge 0
IndexOf() returns -1 if the substring is not found, so any non-negative return value can be interpreted as having found the substring.