There are two issues that need a fix:
\W also matches whitespaces, [\W\s] is equalt to \W. Thus, /[^\W\s]/ should be just /\w/
\W does not match underscores. When you require a special character and an underscore is treated as a special character, you need to use a [\W_] character class
Note also, that regexps used with RegExp#test should never be used with a g flag, it might lead to issues like this (not the case here, but as a best practice). Also, \w matches any lower- and uppercase ASCII letters, so not need to use a case insensitive i modifier here.
So, you may use
return /\w/.test(value) // match any wordCharacter
&& /[a-z]/.test(value) // has a lowercase letter
&& /[A-Z]/.test(value) // has a uppercase letter
&& /\d/.test(value) // has a digit
&& /^[^\W_]*[\W_]/.test(value) // has a specialChar
});
The ^[^\W_]*[\W_] pattern means
^ - match start of string
[^\W_]* - 0 or more chars other than non-word chars or _ (i.e. 0 or more letters or digits)
[\W_] - a non-word char or a _ char.