CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-should

Expressive, readable, framework-agnostic BDD-style assertion library for JavaScript testing.

Pending
Overview
Eval results
Files

string-assertions.mddocs/

String Assertions

Methods for testing string content, patterns, and formatting.

String Pattern Testing

startWith()

Test that a string starts with a specified prefix.

/**
 * Assert that the string starts with the specified prefix
 * @param prefix - The expected prefix string
 * @param description - Optional error message
 * @returns This assertion for chaining
 */
startWith(prefix: string, description?: string): Assertion;

Usage:

import should from 'should';

'hello world'.should.startWith('hello');
'JavaScript'.should.startWith('Java');
'test123'.should.startWith('test');

// Case sensitive
'Hello'.should.not.startWith('hello');
'Hello'.should.startWith('H');

// Empty string
'anything'.should.startWith('');
''.should.startWith('');

// With description
const filename = 'config.json';
filename.should.startWith('config', 'Filename should start with config');

// Chaining with other assertions
const url = 'https://example.com';
url.should.startWith('https').and.be.a.String();

endWith()

Test that a string ends with a specified suffix.

/**
 * Assert that the string ends with the specified suffix
 * @param suffix - The expected suffix string
 * @param description - Optional error message
 * @returns This assertion for chaining
 */
endWith(suffix: string, description?: string): Assertion;

Usage:

'hello world'.should.endWith('world');
'test.js'.should.endWith('.js');
'document.pdf'.should.endWith('.pdf');

// Case sensitive
'Hello'.should.not.endWith('LLO');
'Hello'.should.endWith('o');

// Empty string
'anything'.should.endWith('');
''.should.endWith('');

// With description
const email = 'user@example.com';
email.should.endWith('.com', 'Email should end with .com domain');

// File extension validation
const jsFile = 'script.js';
jsFile.should.endWith('.js').and.be.a.String();

Advanced String Testing

match()

Test that a string matches a pattern, function, or object matcher.

/**
 * Assert that the string matches the specified pattern, function, or object
 * @param pattern - RegExp, function, or object to match against
 * @param description - Optional error message
 * @returns This assertion for chaining
 */
match(pattern: RegExp | Function | object, description?: string): Assertion;

Usage:

// Regular expression matching
'hello123'.should.match(/^hello\d+$/);
'test@example.com'.should.match(/\w+@\w+\.\w+/);
'2023-12-25'.should.match(/^\d{4}-\d{2}-\d{2}$/);

// Case insensitive regex
'Hello World'.should.match(/hello world/i);

// Function matching
'positive123'.should.match(str => str.includes('positive'));
'test'.should.match(str => str.length === 4);

// Object matching (for complex patterns)
const phonePattern = {
  test: (str) => /^\d{3}-\d{3}-\d{4}$/.test(str)
};
'123-456-7890'.should.match(phonePattern);

// With description
const password = 'MyPassword123!';
password.should.match(/^(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])/, 
  'Password should contain uppercase, digit, and special character');

Practical String Validation Examples

Email Validation

function validateEmail(email) {
  email.should.be.a.String();
  email.should.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
  email.should.not.be.empty();
  
  // Additional checks
  email.should.not.startWith('@');
  email.should.not.endWith('@');
  email.should.match(/@/); // Must contain @
}

// Usage
const validEmail = 'user@example.com';
validateEmail(validEmail);

URL Validation

function validateURL(url) {
  url.should.be.a.String();
  url.should.match(/^https?:\/\//); // Must start with http:// or https://
  url.should.not.be.empty();
}

// Protocol-specific validation
function validateHTTPS(url) {
  url.should.startWith('https://');
  url.should.not.startWith('http://');
}

const secureUrl = 'https://secure.example.com';
validateHTTPS(secureUrl);

File Path Validation

function validateJavaScriptFile(filepath) {
  filepath.should.be.a.String();
  filepath.should.endWith('.js');
  filepath.should.not.be.empty();
}

function validateImageFile(filepath) {
  filepath.should.be.a.String();
  filepath.should.match(/\.(jpg|jpeg|png|gif|webp)$/i);
}

const jsFile = 'components/Header.js';
validateJavaScriptFile(jsFile);

const imageFile = 'assets/logo.PNG';
validateImageFile(imageFile);

Format Validation

// Phone number formats
function validatePhoneNumber(phone) {
  phone.should.be.a.String();
  phone.should.match(/^\(\d{3}\) \d{3}-\d{4}$|^\d{3}-\d{3}-\d{4}$/);
}

// Date formats
function validateDateFormat(date) {
  date.should.be.a.String();
  date.should.match(/^\d{4}-\d{2}-\d{2}$/); // YYYY-MM-DD
}

// Time formats
function validateTimeFormat(time) {
  time.should.be.a.String();
  time.should.match(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/); // HH:MM (24-hour)
}

validatePhoneNumber('(555) 123-4567');
validateDateFormat('2023-12-25');
validateTimeFormat('14:30');

Content Validation

// Password strength
function validateStrongPassword(password) {
  password.should.be.a.String();
  password.should.match(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/,
    'Password must contain uppercase, lowercase, digit, special char, min 8 chars');
}

// Username validation
function validateUsername(username) {
  username.should.be.a.String();
  username.should.match(/^[a-zA-Z0-9_-]{3,20}$/);
  username.should.not.startWith('-');
  username.should.not.endWith('-');
}

// HTML tag validation
function validateHTMLTag(tag) {
  tag.should.be.a.String();
  tag.should.startWith('<');
  tag.should.endWith('>');
  tag.should.match(/^<\/?[a-zA-Z][\w-]*(?:\s[^>]*)?>/);
}

validateUsername('user_123');
validateHTMLTag('<div class="container">');

Text Content Analysis

// Check for specific content
function validateContainsKeywords(text, keywords) {
  text.should.be.a.String();
  keywords.forEach(keyword => {
    text.should.match(new RegExp(keyword, 'i')); // Case insensitive
  });
}

// Code validation
function validateJavaScriptCode(code) {
  code.should.be.a.String();
  code.should.not.be.empty();
  
  // Should contain function or variable declarations
  code.should.match(/\b(function|const|let|var|class)\b/);
}

// Markdown validation
function validateMarkdownHeader(text) {
  text.should.be.a.String();
  text.should.startWith('#');
  text.should.match(/^#{1,6}\s+/); // 1-6 # followed by space
}

const jsCode = 'const hello = () => "world";';
validateJavaScriptCode(jsCode);

const header = '## Section Title';
validateMarkdownHeader(header);

String-Specific Methods

String assertions in Should.js focus on content testing, prefix/suffix validation, and pattern matching specifically for string values.

Note: The match() method shown above also works with collections and has additional variants (matchEach(), matchEvery(), matchAny(), matchSome()). These are general collection methods, not string-specific. For complete documentation on pattern matching capabilities, see Pattern Matching.

String Length and Emptiness

String assertions can be combined with length and emptiness tests:

const text = 'Hello World';

// Length validation
text.should.be.a.String().and.have.length(11);
text.should.not.be.empty();

// Pattern with length constraints
const code = 'ABC123';
code.should.match(/^[A-Z]{3}\d{3}$/).and.have.length(6);

// Minimum/maximum length with content validation
const title = 'My Article Title';
title.should.be.a.String()
  .and.have.property('length').above(5)
  .and.below(50);
title.should.not.be.empty();

Case Sensitivity Examples

// Case-sensitive matching
'JavaScript'.should.startWith('Java'); // ✓
'JavaScript'.should.not.startWith('java'); // ✓

'test.JS'.should.endWith('.JS'); // ✓
'test.JS'.should.not.endWith('.js'); // ✓

// Case-insensitive with regex
'Hello World'.should.match(/hello/i); // ✓
'Hello World'.should.not.match(/hello/); // ✓ (case sensitive fails)

// Custom case-insensitive validation
function validateExtension(filename, ext) {
  filename.should.be.a.String();
  filename.should.match(new RegExp(`\\.${ext}$`, 'i'));
}

validateExtension('document.PDF', 'pdf'); // ✓
validateExtension('image.JPG', 'jpg'); // ✓

Negation and Chaining

All string assertions support negation and can be chained:

const filename = 'document.txt';

// Multiple conditions
filename.should.be.a.String()
  .and.not.be.empty()
  .and.startWith('doc')
  .and.endWith('.txt')
  .and.match(/^[a-z]+\.(txt|doc)$/);

// Negation examples
filename.should.not.startWith('test');
filename.should.not.endWith('.js');
filename.should.not.match(/^\d+/); // Should not start with digits

Install with Tessl CLI

npx tessl i tessl/npm-should

docs

basic-assertions.md

configuration.md

containment-assertions.md

error-assertions.md

index.md

number-assertions.md

pattern-matching.md

promise-assertions.md

property-assertions.md

string-assertions.md

type-assertions.md

tile.json