src/arbitraries
fast-check generators for HL7 v2, at @cosyte/hl7/arbitraries: encoding characters, escape
sequences, values, components, repetitions, fields, segments, message types, whole messages,
messy message text, hostile input, and an animal patient's species, breed, strain and production
class. We use them to test this library, and you can use them to test code you build on it.
fast-check is an optional peer dependency: install it to use this entry point. The main
entry point, @cosyte/hl7, never loads it.
Every generated value is synthetic and random. Nothing in one looks like a patient's name, date of birth, address or identifier.
Example
import fc from "fast-check";
import { parseHL7 } from "@cosyte/hl7";
import { message } from "@cosyte/hl7/arbitraries";
fc.assert(
fc.property(message(), (msg) => parseHL7(msg.toString()).toString() === msg.toString()),
);
Interfaces
EncodingCharactersOptions
Options for encodingCharacters.
Properties
delimiters?
readonlyoptionaldelimiters?:"standard"|"any"
"standard" always gives |^~\&; "any" (the default) gives the standard set about half
the time and six distinct punctuation characters otherwise.
truncation?
readonlyoptionaltruncation?:boolean
Whether to declare the v2.7 truncation character (a fifth MSH-2 character). true always
declares one, false never does, and leaving it out declares one about half the time.
EscapeSequenceOptions
Options for escapeSequence.
Properties
encodingCharacters?
readonlyoptionalencodingCharacters?:EncodingCharacters
The encoding characters the sequence is written with. Defaults to the standard set, with no
truncation character, so \P is never generated.
HostileInputOptions
Options for hostileInput.
Properties
maxLength?
readonlyoptionalmaxLength?:number
The longest random string or byte run. Defaults to 200.
MessageOptions
Options for message and messageText.
Properties
encodingCharacters?
readonlyoptionalencodingCharacters?:Arbitrary<EncodingCharacters>
The encoding characters to write with. Defaults to encodingCharacters.
escapes?
readonlyoptionalescapes?:boolean
Whether values carry escape sequences beyond the ones their delimiters need: hex, highlight,
formatting, character set and local escapes. Defaults to true.
maxExtraSegments?
readonlyoptionalmaxExtraSegments?:number
The most segments after the ones a message type opens with. Defaults to 4.
maxFields?
readonlyoptionalmaxFields?:number
The most fields in a body segment. Defaults to 8.
MessageType
A message type: the MSH-9 message code and trigger event.
Properties
code
readonlycode:string
The message code, MSH-9.1, such as ADT.
trigger
readonlytrigger:string
The trigger event, MSH-9.2, such as A01.
SegmentOptions
Options for segment.
Extends
Properties
maxComponents?
readonlyoptionalmaxComponents?:number
The most components in a repetition. Defaults to 4.
Inherited from
maxFields?
readonlyoptionalmaxFields?:number
The most fields after the name. Defaults to 8.
maxRepetitions?
readonlyoptionalmaxRepetitions?:number
The most repetitions in a field. Defaults to 3.
Inherited from
maxSubcomponents?
readonlyoptionalmaxSubcomponents?:number
The most subcomponents in a component. Defaults to 3.
Inherited from
names?
readonlyoptionalnames?: readonlystring[]
The names to draw from. Defaults to common segments and site-defined Z segments. A name
is three characters; MSH and the batch envelope segments are not body segments.
nullable?
readonlyoptionalnullable?:boolean
Whether a field may be the explicit null "". Defaults to true.
Inherited from
values?
readonlyoptionalvalues?:Arbitrary<string>
The decoded values at the leaves. Defaults to value.
Inherited from
TreeOptions
The shape options every level of the tree takes.
Extended by
Properties
maxComponents?
readonlyoptionalmaxComponents?:number
The most components in a repetition. Defaults to 4.
maxRepetitions?
readonlyoptionalmaxRepetitions?:number
The most repetitions in a field. Defaults to 3.
maxSubcomponents?
readonlyoptionalmaxSubcomponents?:number
The most subcomponents in a component. Defaults to 3.
nullable?
readonlyoptionalnullable?:boolean
Whether a field may be the explicit null "". Defaults to true.
values?
readonlyoptionalvalues?:Arbitrary<string>
The decoded values at the leaves. Defaults to value.
ValueOptions
Options for value.
Properties
maxLength?
readonlyoptionalmaxLength?:number
The longest value, in characters. Defaults to 12.
minLength?
readonlyoptionalminLength?:number
The shortest value, at least 1. Defaults to 1.
Functions
breed()
breed():
Arbitrary<CWE>
Generate a PID-36 Breed Code: a random coded value, never a real breed code.
Returns
Arbitrary<CWE>
An arbitrary of the code, the shape Patient.breed reads and AdtPatient.breed takes.
Example
import fc from "fast-check";
import { breed } from "@cosyte/hl7/arbitraries";
const [code] = fc.sample(breed(), 1);
// code is a CWE with at least one part
component()
component(
options?):Arbitrary<RawComponent>
Generate one component: a list of decoded subcomponents, ending on a non-empty one, with empty subcomponents allowed before it.
Parameters
options?
TreeOptions = {}
The tree's bounds and its leaf values.
Returns
Arbitrary<RawComponent>
An arbitrary of a RawComponent.
Example
import fc from "fast-check";
import { component } from "@cosyte/hl7/arbitraries";
const [comp] = fc.sample(component({ maxSubcomponents: 2 }), 1);
// comp is like { subcomponents: ["", "x&y"] }
encodingCharacters()
encodingCharacters(
options?):Arbitrary<EncodingCharacters>
Generate a set of HL7 encoding characters: the field separator (MSH-1) and the MSH-2 characters, all distinct, optionally with the v2.7 truncation character.
Parameters
options?
EncodingCharactersOptions = {}
Which delimiters to draw and whether to declare a truncation character.
Returns
Arbitrary<EncodingCharacters>
An arbitrary of EncodingCharacters.
Example
import fc from "fast-check";
import { encodingCharacters } from "@cosyte/hl7/arbitraries";
const [enc] = fc.sample(encodingCharacters({ delimiters: "standard", truncation: false }), 1);
// enc is { field: "|", component: "^", repetition: "~", escape: "\\", subcomponent: "&" }
escapeSequence()
escapeSequence(
options?):Arbitrary<string>
Generate one HL7 escape sequence as it is written on the wire, delimited by the escape
character: a delimiter escape (\F\, \S, \T\, \R, \E\, and \P when a truncation
character is declared), the line break \.br\, a hex escape (\X41), a highlight, formatting
or character set escape (\H\, \.sp, \C2842\), or a local \Z.. escape.
Parameters
options?
The encoding characters to write it with.
Returns
Arbitrary<string>
An arbitrary of the escape sequence's wire text.
Example
import fc from "fast-check";
import { escapeSequence } from "@cosyte/hl7/arbitraries";
const [token] = fc.sample(escapeSequence(), 1);
// token is one sequence, such as "\\F\\" or "\\X0D\\"
field()
field(
options?):Arbitrary<RawField>
Generate one field in the shape the parser builds: repetitions of components of decoded
subcomponents, with empty items allowed anywhere but at the end of each list, or, about one
time in ten unless nullable is false, the explicit null "".
Parameters
options?
TreeOptions = {}
The tree's bounds and its leaf values.
Returns
Arbitrary<RawField>
An arbitrary of a RawField.
Example
import fc from "fast-check";
import { buildMessage } from "@cosyte/hl7";
import { field } from "@cosyte/hl7/arbitraries";
const [f] = fc.sample(field({ nullable: false }), 1);
const msg = buildMessage({ type: "ADT^A01", controlId: "CTRL1" });
msg.addSegment("ZXX", [f]);
hostileInput()
hostileInput(
options?):Arbitrary<string|Buffer<ArrayBufferLike>>
Generate hostile input for a lenient parser: random strings, random bytes, messages with random cuts, deletions and insertions, text that opens like an MSH and then falls apart, and messages as bytes in UTF-8 or Latin-1. The parser must turn each into a message with warnings, or refuse it with one of its documented fatal errors, and never throw anything else.
Parameters
options?
HostileInputOptions = {}
The longest random run.
Returns
Arbitrary<string | Buffer<ArrayBufferLike>>
An arbitrary of a string or a Buffer.
Example
import fc from "fast-check";
import { Hl7ParseError, parseHL7 } from "@cosyte/hl7";
import { hostileInput } from "@cosyte/hl7/arbitraries";
fc.assert(
fc.property(hostileInput(), (raw) => {
try {
parseHL7(raw);
} catch (err) {
return err instanceof Hl7ParseError;
}
return true;
}),
);
message()
message(
options?):Arbitrary<Hl7Message>
Generate a spec-clean message, parsed: written over generated encoding characters with escape
sequences in its values, and never anything the parser would have to repair, so the message
serializes back to the text it was parsed from. Its MSH carries a common message type and the
body opens with that type's segments, then adds generated segments, Z segments included.
Every value is random: nothing in one looks like a name, a date of birth or an identifier.
Each case is a new message, so the code under test may change it.
Parameters
options?
MessageOptions = {}
The encoding characters, the size, and whether to add escape sequences.
Returns
Arbitrary<Hl7Message>
An arbitrary of an Hl7Message.
Example
import fc from "fast-check";
import { parseHL7 } from "@cosyte/hl7";
import { message } from "@cosyte/hl7/arbitraries";
fc.assert(
fc.property(message(), (msg) => {
return parseHL7(msg.toString()).toString() === msg.toString();
}),
);
messageText()
messageText(
options?):Arbitrary<string>
Generate raw message text the parser accepts, messy on purpose: line endings of any kind, MLLP framing, a byte order mark, padded fields, trailing delimiters, fields of separators only, lower-case segment names, unknown and unterminated escapes, unknown segments and a character set in MSH-18. The parser reads past each one, repairing what it must, and never refuses it, so this text always parses.
Parameters
options?
MessageOptions = {}
The encoding characters, the size, and whether to add escape sequences.
Returns
Arbitrary<string>
An arbitrary of the message text.
Example
import fc from "fast-check";
import { parseHL7 } from "@cosyte/hl7";
import { messageText } from "@cosyte/hl7/arbitraries";
fc.assert(
fc.property(messageText(), (raw) => {
parseHL7(raw); // never throws for this text
}),
);
messageType()
messageType():
Arbitrary<MessageType>
Generate a common message type: ADT (A01, A03, A04, A08), ORU^R01, ORM^O01, OML^O21, SIU^S12, MDM^T02, DFT^P03, VXU^V04, RDE^O11 or ACK.
Returns
Arbitrary<MessageType>
An arbitrary of a MessageType.
Example
import fc from "fast-check";
import { messageType } from "@cosyte/hl7/arbitraries";
const [type] = fc.sample(messageType(), 1);
// type is like { code: "ORU", trigger: "R01" }
productionClass()
productionClass():
Arbitrary<CWE>
Generate a PID-38 Production Class Code: a random coded value, never a real class code.
Returns
Arbitrary<CWE>
An arbitrary of the code, the shape Patient.productionClass reads and
AdtPatient.productionClass takes.
Example
import fc from "fast-check";
import { productionClass } from "@cosyte/hl7/arbitraries";
const [code] = fc.sample(productionClass(), 1);
// code is a CWE with at least one part
repetition()
repetition(
options?):Arbitrary<RawRepetition>
Generate one repetition: a list of components ending on a non-empty one.
Parameters
options?
TreeOptions = {}
The tree's bounds and its leaf values.
Returns
Arbitrary<RawRepetition>
An arbitrary of a RawRepetition.
Example
import fc from "fast-check";
import { repetition } from "@cosyte/hl7/arbitraries";
const [rep] = fc.sample(repetition(), 1);
// rep is like { components: [{ subcomponents: ["A1"] }, { subcomponents: ["b"] }] }
segment()
segment(
options?):Arbitrary<RawSegment>
Generate one non-MSH segment in the shape the parser builds: fields[0] holds the name, and
fields 1 and up are generated fields, ending on a non-empty one.
Parameters
options?
SegmentOptions = {}
The names, the field count and the tree's bounds.
Returns
Arbitrary<RawSegment>
An arbitrary of a RawSegment.
Example
import fc from "fast-check";
import { segment } from "@cosyte/hl7/arbitraries";
const [seg] = fc.sample(segment({ names: ["NTE"], maxFields: 3 }), 1);
seg?.name; // "NTE"
species()
species():
Arbitrary<CWE>
Generate a PID-35 Species Code: a random coded value, never a real species code.
Returns
Arbitrary<CWE>
An arbitrary of the code, the shape Patient.species reads and AdtPatient.species
takes.
Example
import fc from "fast-check";
import { species } from "@cosyte/hl7/arbitraries";
const [code] = fc.sample(species(), 1);
// code is a CWE with at least one part, such as { identifier: "Q7", text: "a^b" }
strain()
strain():
Arbitrary<string>
Generate a PID-37 Strain: one random decoded value, the free text Patient.strain reads and
AdtPatient.strain takes.
Returns
Arbitrary<string>
An arbitrary of the strain text.
Example
import fc from "fast-check";
import { strain } from "@cosyte/hl7/arbitraries";
const [text] = fc.sample(strain(), 1);
// text is a non-empty string, such as "x&Y"
value()
value(
options?):Arbitrary<string>
Generate one decoded value, the text of a subcomponent as a reader sees it: never empty, never
the explicit null "", and never starting or ending with a space, so the parser has nothing
to trim. It mixes in the delimiters, the line break and the carriage return, so writing it
needs escape sequences.
Parameters
options?
ValueOptions = {}
Its length bounds.
Returns
Arbitrary<string>
An arbitrary of the value.
Example
import fc from "fast-check";
import { value } from "@cosyte/hl7/arbitraries";
const [text] = fc.sample(value({ maxLength: 4 }), 1);
// text is up to four characters, such as "a|Z" or "Q"