
Company News
Socket Named Top Sales Organization by RepVue
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.
o-check-list
Advanced tools
Validations, assertions and tests for conditions on objects
npm install o-check-list
http://o-programming-language.org/
Validate that an object satisfies one or more conditions.
If a validation fails it raises a ConditionCheckFailure
const { validation } = require('o-check-list')
const user = new User()
validation((validate) => {
validate.that(user).isNotNull()
validate.that(user.name).isNotBlank()
})
Get a validation result instead of raising an error with validate.whether
const { validation } = require('o-check-list')
const user = new User()
validation((validate) => {
validate.whether(user).isNotNull()
validate.whether(user.name).isNotBlank()
})
validate.whether does not use try/catch
Assertions are like validations with the option to be globally disabled
const { GlobalAssertion } = require('o-check-list')
GlobalAssertion.disableAssertions()
GlobalAssertion.enableAssertions()
GlobalAssertion.isAssertionsEnabled()
For instance, to disable assertions in a production environment do
const { GlobalAssertion } = require('o-check-list')
if (process.env.NODE_ENV === 'production') {
GlobalAssertion.disableAssertions()
}
If assertions are disabled the assertion block is not evaluated
If assertions are enabled they behave the same as validations do
const { assertion } = require('o-check-list')
const user = new User()
validation((assertion) => {
assertion.that(user).isNotNull()
assertion.that(user.name).isNotBlank()
})
Assertions are usually part of a development and debugging process, whereas validations are part of the program logic
Test stateful objects with sequencial steps, organized as one or more use cases of a functional story
const { story } = require('o-check-list')
story('Removes an element from a Set', (story) => {
story.useCase('Remove an existing element from a Set', (exec) => {
let set
exec.step('let be an empty set', () => {
set = new Set()
})
exec.step('then add an element', () => {
set.add('item')
})
exec.step('then the element is present', (assure) => {
assure.that('item').isIncludedIn(set)
})
exec.step('then remove the element', () => {
set.delete('item')
})
exec.step('then the element is not present', (assure) => {
assure.that('item').isNotIncludedIn(set)
})
})
story.useCase('Remove an absent element from a Set', (exec) => {
let set
exec.step('let be an empty set', () => {
set = new Set()
})
exec.step('then the element is not present', (assure) => {
assure.that('item').isNotIncludedIn(set)
})
exec.step('then remove the element', () => {
set.delete('item')
})
exec.step('then the element is not present', (assure) => {
assure.that('item').isNotIncludedIn(set)
})
})
})
Because of its sequential nature, rather than a declarative nature, testing asynchronous code in o-check-list is pretty much the same as testing synchronous code
Add exec.beAsync() at the beginning of each async story.useCase, and that's it
E.g.
const { story } = require('o-check-list')
story('Call an asynchronous method', (story) => {
story.useCase('Fetch data from a remote server', (exec) => {
let remoteServer
let fetchedData
exec.beAsync()
exec.step('Given a RemoteServer', () => {
remoteServer = new RemoteServer()
})
exec.step('then, fetch ask it for data', async () => {
fetchedData = await remoteServer.fetchData()
})
exec.step('then, data is as expected', (assure) => {
assure.that( fetchedData ).equals( 'something' )
})
})
})
If you ever forget to flag the story as exec.beAsync(), yet some step is asynchronous, o-check-list will kindly remember you to add it
To test only one or a few stories or useCases from the whole suite, include any number of alone() and ignore() statements in any story or useCase
const { story } = require('o-check-list')
story('Removes an element from a Set', (story) => {
story.useCase('Remove an existing element from a Set', (exec) => {
exec.alone() // <-- ignore all other useCases not flagged with .alone() as well
let set
exec.step('let be an empty set', () => {
set = new Set()
})
exec.step('then add an element', () => {
set.add('item')
})
exec.step('then the element is present', (assure) => {
assure.that('item').isIncludedIn(set)
})
exec.step('then remove the element', () => {
set.delete('item')
})
exec.step('then the element is not present', (assure) => {
assure.that('item').isNotIncludedIn(set)
})
})
story.useCase('Remove an absent element from a Set', (exec) => {
let set
exec.step('let be an empty set', () => {
set = new Set()
})
exec.step('then the element is not present', (assure) => {
assure.that('item').isNotIncludedIn(set)
})
exec.step('then remove the element', () => {
set.delete('item')
})
exec.step('then the element is not present', (assure) => {
assure.that('item').isNotIncludedIn(set)
})
})
})
Stories are regular javascript objects, they can be collected and run in any regular javascript context
Create a test and get the result of its evaluation
const { GlobalStories } = require('o-check-list')
const stories = GlobalStories.createStoriesContext()
const checks = stories.story('Removes an element from a Set', (story) => {
story.useCase('Remove an existing element from a Set', (exec) => {
let set
exec.step('let be an empty set', () => {
set = new Set()
})
exec.step('then add an element', () => {
set.add('item')
})
exec.step('then the element is present', (assure) => {
assure.whether('item').isIncludedIn(set)
})
exec.step('then remove the element', () => {
set.delete('item')
})
exec.step('then the element is not present', (assure) => {
assure.whether('item').isNotIncludedIn(set)
})
})
story.useCase('Remove an absent element from a Set', (exec) => {
let set
exec.step('let be an empty set', () => {
set = new Set()
})
exec.step('then the element is not present', (assure) => {
assure.whether('item').isNotIncludedIn(set)
})
exec.step('then remove the element', () => {
set.delete('item')
})
exec.step('then the element is not present', (assure) => {
assure.whether('item').isNotIncludedIn(set)
})
})
})
const checkResults = checks.evaluate()
checkResults.isValid() === true
Custom checks are subclasses of ConditionCheck
const ConditionCheck = require('o-checklist')
class IsString extends ConditionCheck {
getCheckId () {
return 'isString'
}
evaluateConditionOn ({ subject, params, result, evaluationContext }) {
if (typeof (subject) === 'string') { return }
const subjectString = this.displayString(subject)
result.beNotValid({
reason: `Expected a string, got ${subjectString}`
})
}
}
module.exports = IsString
Add custom checks globally, in a story or in a use case with registerCheck method
const { story, GlobalStories } = require('o-check-list')
const isStringChecker = new IsString()
// Add the custom checker for all stories
GlobalStories.registerCheck({ checkMethodName: 'isString', conditionChecker: isStringChecker })
story('...', (story) => {
// or only for this story
story.registerCheck({ checkMethodName: 'isString', conditionChecker: isStringChecker })
story.useCase('...', (exec) => {
// or only for this useCase
story.registerCheck({ checkMethodName: 'isString', conditionChecker: isStringChecker })
})
})
All checks in o-check-list, validations, assertions and tests, share the same underlaying implementation
The implementation can run without using exceptions at all with the use of .whether(...) instead of .that(...)
To perform setup/tearDown actions, before and after each UseCase execution, do
GlobalStories.beforeEachExecution( () => {
setupSomething()
})
GlobalStories.afterEachExecution( () => {
tearDownSomething()
})
story('...', (story) => {
story.beforeEachExecution( () => {
setupSomething()
})
story.afterEachExecution( () => {
tearDownSomething()
})
story.useCase('...', (exec) => {
exec.beforeEachExecution( () => {
setupSomething()
})
exec.afterEachExecution( () => {
tearDownSomething()
})
})
})
At the moment, there are no beforeAllExecution, afterAllExecution methods, for it seems to be more on the test runner protocol, rather than on the definition of the tests
o-check-list has a limited test runner
To run tests in the directory ./tests and ./examples within the project, execute
npx checklist
To run tests in a directory different than the default one, execute
npx checklist testsDirectory ./tests
To filter tests based on their description, execute
npx checklist testsDirectory ./tests filter "Removes an element from a Set"
Since o-check-list is regular javascript objects and methods, it's faily possible to implement a custom runner, both in Node.js and Browser sides, though
DoMe commands are intended to be self-documented, please take a look at the files in DoMe/forDevelopment/inWindows
FAQs
Check for conditions on objects
We found that o-check-list demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.

Company News
/Security News
Socket is an initial recipient of OpenAI's Cybersecurity Grant Program, which commits $10M in API credits to defenders securing open source software.