persevere-js
v1.5.0
Published
A utility that perseveres
Downloads
328
Maintainers
Readme
Description
A small utility that provides an easy-to-read syntax for awaiting on a condition to be satisfied. This makes testing asynchronous logic a breeze!
Heavily inspired by Awaitility which is a Java utility aimed at testing asynchronous systems.
Example
This utility could be used in both production and test code, but primarily use cases tend towards the latter.
For this example, imagine a simple backend for a local book store. The developer of the system wants to check the asynchronous 'real time' stocking system, which utilises a message queue. The flow for this is as follows:
- Customer purchases a book
- Purchase is placed onto a messaging queue for asynchronous processing
- The message is consumed at some point later (usually milliseconds, sometimes seconds, but never more than 10 seconds) later by the bookstore backend
- The books quantity is decremented by 1 in the database
The developer sets up the following simple test for this, thanks to PersevereJS
🚀
import { persevereFor } from "persevere-js";
describe('Stocking Tests', () => {
it('should decrement stock quantity, when a book is purchased', async () => {
// Given
const book = new Book('Harry Potter and the Philosophers Stone')
// When
bookService.addPurchaseToQueue(book)
// Then
await persevereFor().atMost(10, 'SECONDS').until(() => bookRepository.getStockCountFor(book)).yieldsValue(0)
})
})
In the above example, one of two things will happen:
- The stock count will become 0 for the book within the allotted 10-second period.
- The purchase message is never consumer, or takes longer than 10 seconds to be delivered and an exception will be thrown.
Usage
By chaining temporal bindings and until conditions, you can craft powerful mechanisms to wait for asynchronous conditions to satisfy.
The entrypoint into the wonderful world of waiting is the persevereFor
function (note: persevere
is also available and is functionally identical).
// Wait for at most 30 seconds, for there to be an order from bob in the databsse
await persevereFor()
.atMost(30, 'SECONDS')
.until(async () => {
return db.query('SELECT ORDER_ID, CUSTOMER_ID FROM CUSTOMER_ORDERS');
})
.satisfies((customerOrders: { orderId: string, customerId: string}[]) => {
return customerOrders
.find(order => order.customerId = 'bob') != undefined;
})
Temporal Bindings
You can utilise the following temporal bindings for your persevere functions:
atMost
- Wait for at most the specified time for the condition to be met.atLeast
- Expect that at least the specified time has passed before the condition is met. (Note: Must also provide an upper temporal bound).
Until Conditions
You can utilise the following until conditions for determining success
yieldsValue
- Stop waiting once the underlying promissory function yields the value specified.satisfies
- Stop waiting once the underlying promissory function satisfies the provided predicate.noExceptions
- Stop waiting as soon as the underlying promissory function resolves (doesn't reject/throw).
Licence
Copyright (c) 2023 James McNee Licensed under the MIT license.
This README was generated with ❤️ by readme-md-generator