# A DSL for Testing in JavaScript

Given an array:

``var xs = [2, 4, 8, 16];``

Write from scratch a library to check the values of elements within it:

``````forArray(xs).elemAt(3).shouldBe(equalTo(16));
// throws no exceptions

// forArray(xs).elemAt(2).shouldBe(equalTo(16));
// throws "expected 16 at index 2, but found 8"

// forArray(xs).elemAt(4).shouldBe(equalTo(16));
// throws "expected 16 at index 4, but the largest valid index is 3"

console.log('Finished without exceptions!')``````

## Bonus

Add support for checking other characteristics of the elements:

``````forArray(xs).elemAt(3).shouldBe(atLeast(16));
// throws no exceptions

// forArray(xs).elemAt(2).shouldBe(greaterThan(8));
// throws "expected a value greater than 8 at index 2, but found 8"``````
``````forArray(xs).elemAt(3).shouldBe(even());
// throws no exceptions

// forArray(xs).elemAt(3).shouldBe(odd());
// throws "expected an odd number at index 3, but found 16"

console.log('Finished bonus without exceptions!')``````

# Solution

Here is one possible solution.
``````function forArray(xs) {
return {
elemAt: function(index) {
return {
shouldBe: function(comparator) {
comparator(xs, index);
},
};
},
};
}

function equalTo(expected) {
return function(xs, index) {
if (index >= xs.length) {
throw 'expected ' + expected + ' at index ' + index +
', but the largest valid index is ' + (xs.length - 1);
} else if (expected !== xs[index]) {
throw 'expected ' + expected + ' at index ' + index +
', but found ' + xs[index] + '';
}
};
}``````

## Bonus

``````function checkLength(xs, index) {
if (index >= xs.length) {
throw 'expected a value at index ' + index +
', but the largest valid index is ' + (xs.length - 1);
}
}

function atLeast(value) {
return function(xs, index) {
checkLength(xs, index);
if (value > xs[index]) {
throw 'expected a value of at least ' + value + ' at index ' + index +
', but found ' + xs[index] + '';
}
};
}

function greaterThan(value) {
return function(xs, index) {
checkLength(xs, index);
if (value <= xs[index]) {
throw 'expected a value greater than ' + value + ' at index ' + index +
', but found ' + xs[index] + '';
}
};
}

function even() {
return function(xs, index) {
checkLength(xs, index);
if (xs[index] % 2 !== 0) {
throw 'expected an even number at index ' + index +
', but found ' + xs[index] + '';
}
};
}

function odd() {
return function(xs, index) {
checkLength(xs, index);
if (xs[index] % 2 !== 1) {
throw 'expected an odd number at index ' + index +
', but found ' + xs[index] + '';
}
};
}``````

## Demo

This file is literate JavaScript, and can be run using Codedown:

``````\$ curl https://earldouglas.com/posts/exercises/javascript-testing.md |
codedown javascript |
node
Finished without exceptions!
Finished bonus without exceptions!``````