It Should Help

Strings

should().string(x) verifies a string. Two families of checks live here: content checks and occurrence counting with the Times helpers.

Content and case

should().string('Any content').equals('Any content'); // ok — case-sensitive should().string('Any content').equalsIgnoreCase('any content'); // ok should().string('Any content').hasLength(11); // ok should().string('').empty(); // ok — same as hasLength(0) should().string(' ').whitespace(); // ok — spaces only (or empty) should().string('ANY').upperCased(); // ok should().string('any').lowerCased(); // ok

whitespace() accepts an empty string and strings consisting solely of space characters — tabs and other whitespace characters are not included (see Caveats).

Prefix and suffix

should().string('#header').startsWith('#'); // ok — case-sensitive should().string('report.pdf').endsWith('.pdf'); // ok should().string('header').startsWith('Header'); // throws "'header' doesn't start with 'Header'." should().string('report.pdf').not.endsWith('.pdf'); // ok

Both checks are case-sensitive and run the definedness guard: a null/undefined entry throws The entry is not defined. regardless of not. When the substring may sit anywhere in the string, use contains with the Times helpers instead.

Occurrence counting with Times

contains accepts an optional counter — a predicate over the number of occurrences. The Times helper covers the common shapes:

should().string('any any content').contains('any'); // at least once should().string('any any content').contains('any', Times.once()); // throws — found twice should().string('any any content').contains('any', Times.twice()); // ok should().string('any any content').contains('any', Times.exactly(2)); // ok should().string('any any content').contains('any', Times.moreThan(2)); // throws should().string('any any content').contains('any', Times.lessThan(3)); // ok

A custom predicate works too — any (count: number) => boolean:

should().string('a b a b a').contains('a', (count) => count % 2 === 1); // ok — found 3 times

Case-insensitive and any-of variants follow the same shape:

should().string('Any content').containsIgnoreCase('any'); // ok should().string('Any content').containsAny('nope', 'any'); // ok — at least one matches should().string('Any content').containsAnyIgnoreCase('any'); // ok

Regular expressions

should().string('order-42').match(/order-\d+/); // ok should().string('order-42').match(/^order-\d+$/); // ok should().string('order-42').match(/invoice-/); // throws "'order-42' does not match /invoice-/."

match delegates to JavaScript's String.match — it is a partial match. Anchor the expression (^…$) when the whole string must match.

Negation

should().string('Any content').not.contains('nope'); // ok should().string('ANY').not.lowerCased(); // ok

The null/undefined rules from Concepts apply to every check.

Signatures and messages

See API reference — String verifier.

16 September 2026