Skip to content

Commit

Permalink
feat: unit testing
Browse files Browse the repository at this point in the history
- unit testing fixed a few errors in the code
- only 3 unit testing is failing... will fix later.

#4

[ci skip]
  • Loading branch information
Bugs5382 committed Dec 9, 2023
1 parent f96a9d2 commit 65f09a1
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 55 deletions.
169 changes: 148 additions & 21 deletions __tests__/hl7.build.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {randomUUID} from "crypto";
import {EmptyNode} from "../src/builder/modules/emptyNode";
import * as Util from '../src/utils/'
import {Batch, Message} from "../src";

Expand All @@ -24,7 +25,7 @@ describe('node hl7 client - builder tests', () => {

test("error - Message Object - text must start with MSH ", async () => {
try {
new Message({ text: "PV1|||||||^Jones\rMSH|^~\\&\r"})
new Message({ text: "PV1|||||||^Jones\r"})
} catch (err) {
expect(err).toEqual(new Error('text must begin with the MSH segment.'))
}
Expand Down Expand Up @@ -143,7 +144,7 @@ describe('node hl7 client - builder tests', () => {

})

describe(`'build message basics`, () => {
describe('build message basics', () => {

let message: Message
const randomControlID = randomUUID()
Expand All @@ -160,12 +161,12 @@ describe('node hl7 client - builder tests', () => {
})
})

test("... initial build", async () => {
test("...initial build", async () => {
expect(message.toString()).toContain("MSH|^~\\&")
expect(message.toString()).toContain(`|ADT^A01^ADT_A01|${randomControlID}||2.7`)
})

test("... verify MSH header is correct", async () => {
test("...verify MSH header is correct", async () => {
expect(message.toString().substring(0, 8)).toBe("MSH|^~\\&")
expect(message.get('MSH.1').toString()).toBe("|")
expect(message.get('MSH.2').toString()).toBe("^~\\&")
Expand All @@ -177,7 +178,7 @@ describe('node hl7 client - builder tests', () => {
expect(message.get('MSH.12').toString()).toBe("2.7")
})

test('... add onto the MSH header', async () => {
test('...add onto the MSH header', async () => {
message.set("MSH.3", "SendingApp");
message.set("MSH.4", "SendingFacility");
message.set("MSH.5", "ReceivingApp");
Expand All @@ -189,23 +190,21 @@ describe('node hl7 client - builder tests', () => {
expect(message.get("MSH.6").toString()).toBe( "ReceivingFacility");
})

test.todo('...override MSH.7 to short - error out')

test.todo('...override MSH.7 to long - error out')

test('... MSH.3.1 can be gotten with MSH.3', async () => {
test('...MSH.3.1 can be gotten with MSH.3', async () => {
message.set("MSH.3.1", "SendingApp");
expect(message.get("MSH.3").toString()).toBe("SendingApp");
})

test('... MSH.3 can be gotten with MSH.3.1', async () => {
test('...MSH.3 can be gotten with MSH.3.1', async () => {
message.set("MSH.3", "SendingApp");
expect(message.get("MSH.3.1").toString()).toBe("SendingApp");
})



})

describe('complex builder message tests', () => {
describe('complex builder message', () => {

let message: Message

Expand All @@ -222,26 +221,105 @@ describe('node hl7 client - builder tests', () => {
message.set('MSH.7', '20081231')
})

// this is currently failing
test("...should accept a number as a value", async () => {
message.set("EVN.2", 1);
expect(message.toString()).toContain("EVN||1");
});

test('...should accept a Date without time as a value', () => {
message.set("PV1.1", new Date(2012, 9, 31));
expect(message.toString()).toContain( "PV1|20121031");
});

test('...should accept a Date with time as a value', () => {
message.set("PV1.1", new Date(2012, 9, 31, 22, 51, 13));
expect(message.toString()).toContain( "PV1|20121031225113");
});

test('...should accept a float as a value', () => {
message.set("PV1.1", 1.2);
expect(message.toString()).toContain( "PV1|1.2");
});

test('...should accept a boolean as a value', () => {
message.set("PV1.1", true);
expect(message.toString()).toContain( "PV1|Y");
message.set("PV1.1", false);
expect(message.toString()).toContain( "PV1|N");
});

test('...should set the specified field', () => {
message.set("PID.4", "1273462894723");
expect(message.toString()).toContain( "PID||||1273462894723");
});

test('...should be able to set more than one field on the same segment', () => {
message.set("PID.4", "1273462894723");
message.set("PID.10", "TEST");
expect(message.toString()).toContain("PID||||1273462894723||||||TEST");
});

test('...should set the specified component', () => {
message.set("PV1.7.2", "Jones");
expect(message.toString()).toContain( "PV1|||||||^Jones");
});

test('...should be able to set more that one component on the same field', () => {
message.set("PV1.7.2", "Jones");
message.set("PV1.7.3", "John");
expect(message.toString()).toContain("PV1|||||||^Jones^John");
});

test('...should be able to set repeating fields', async () => {
message.set('PID.3').set(0).set('PID.3.1', 'abc');
message.set('PID.3').set(0).set('PID.3.5', 'MRN');
message.set('PID.3').set(1).set('PID.3.1', 123);
message.set('PID.3').set(1).set('PID.3.5', 'ID');
expect(message.toString()).toContain("PID|||abc^^^^MRN~123^^^^ID");
});

test('...can chain component setters', async () => {
message.set("PV1.7").set(0).set("PV1.7.2", "Jones").set("PV1.7.3", "John");
message.set("PV1.7").set(1).set("PV1.7.2", "Smith").set("PV1.7.3", "Bob");
expect(message.toString()).toContain("PV1|||||||^Jones^John~^Smith^Bob");
});

test('...can chain component setters with numeric indexers', async () => {
message.set("PV1.7").set(0).set(1, "Jones").set(2, "John");
message.set("PV1.7").set(1).set(1, "Smith").set(2, "Bob");
expect(message.toString()).toContain("PV1|||||||^Jones^John~^Smith^Bob");
});

test('...can set field component by number', async () => {
message.set("PV1.7").set(0).set(1, "Jones").set(2, "John");
expect(message.toString()).toContain("PV1|||||||^Jones^John");
});

test('...can set field component by number and array', async () => {
message.set("PV1.7").set(0, ["", "Jones", "John"]).set(1, ["", "Smith", "Bob"]);
expect(message.toString()).toContain("PV1|||||||^Jones^John~^Smith^Bob");
});

// This is currently failing, why... I have no idea. Help!
test.skip('... add segment EVN field - using full path', async () => {
const segment = message.addSegment('EVN')
segment.set('EVN.2.1', '20081231')
expect(message.toString()).toBe("MSH|^~\\&|||||20081231||ADT^A01^ADT_A01|12345||2.7\rEVN||20081231")
})

test('... add segment EVN field - using number path', async () => {
test('...add segment EVN field - using number path', async () => {
const segment = message.addSegment('EVN')
segment.set('2.1', '20081231')
expect(message.toString()).toBe("MSH|^~\\&|||||20081231||ADT^A01^ADT_A01|12345||2.7\rEVN||20081231")
})

test('... add segment EVN field - using simple number path', async () => {
test('...add segment EVN field - using simple number path', async () => {
const segment = message.addSegment('EVN')
segment.set('2', '20081231')
expect(message.toString()).toBe("MSH|^~\\&|||||20081231||ADT^A01^ADT_A01|12345||2.7\rEVN||20081231")
})

test('... add segment EVN field - using simple number', async () => {
test('...add segment EVN field - using simple number', async () => {
const segment = message.addSegment('EVN')
segment.set(2, '20081231')
expect(message.toString()).toBe("MSH|^~\\&|||||20081231||ADT^A01^ADT_A01|12345||2.7\rEVN||20081231")
Expand Down Expand Up @@ -286,13 +364,9 @@ describe('node hl7 client - builder tests', () => {
expect(batch.toString()).toBe("BHS|^~\\&|SendingApp|SendingFacility|ReceivingApp|ReceivingFacility|20081231\rBTS|0")
})

test.todo('...override BSH.7 to short - error out')

test.todo('...override BSH.7 to long - error out')

})

describe('complex builder batch tests', () => {
describe('complex builder batch', () => {

let batch: Batch
let message: Message
Expand Down Expand Up @@ -389,4 +463,57 @@ describe('node hl7 client - builder tests', () => {

})

describe('non standard tests', () => {

test('...returns true if specified path exists', () => {
let message = new Message({text:"MSH|^~\\&|value\rPV1|"});
expect(message.exists("MSH.3")).toBe(true)
expect(message.exists("PV1")).toBe(true)
});

test('...returns false if specified path does not exists', () => {
let message = new Message({text: "MSH|^~\\&|value"});
expect(message.exists("MSH.4")).toBe(false)
expect(message.exists("PV1")).toBe(false)
});

test('...should return EmptyNode for out-of-range indexes', () => {
let message = new Message({text: "MSH|^~\\&|"});
expect(message.get(10)).toBeInstanceOf(EmptyNode)
expect(message.get("PV1").get(10)).toBeInstanceOf(EmptyNode)
});

test('...should resolve escape sequence for hex character sequence', () => {
let field = new Message({text: "MSH|^~\\&|\\X0D\\"}).get("MSH.3");
expect(field.toString()).toBe("\r");
})

test('...should pass through invalid escape sequences', () => {
expect(new Message({text: "MSH|^~\\&|\\a\\"}).get("MSH.3").toString()).toBe("\\a\\")
})

})

describe('parse message', () => {

const hl7_string: string = "MSH|^~\\&|||||20081231||ADT^A01^ADT_A01|12345||2.7\rEVN||20081231"

test('...verify input', async () => {

const message = new Message({text: hl7_string})

expect(message.toString().substring(0, 8)).toBe("MSH|^~\\&")
expect(message.get('MSH.1').toString()).toBe("|")
expect(message.get('MSH.2').toString()).toBe("^~\\&")
expect(message.get('MSH.3').exists("")).toBe(false)
expect(message.get('MSH.9.1').toString()).toBe("ADT")
expect(message.get('MSH.9.2').toString()).toBe("A01")
expect(message.get('MSH.9.3').toString()).toBe("ADT_A01")
expect(message.get('MSH.10').toString()).toBe("12345")
expect(message.get('MSH.12').toString()).toBe("2.7")
expect(message.get('EVN.2').toString()).toBe("20081231")
})

})

})
14 changes: 6 additions & 8 deletions src/builder/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ export class Message extends RootBase {
this.set('MSH.10', this._opt.messageHeader.msh_10.toString())
this.set('MSH.12', this._opt.specification.name.toString())
}
} else {
throw new HL7FatalError(500, 'Unable to fully build a new HL7 message.')
}
}

Expand Down Expand Up @@ -94,7 +92,6 @@ export class Message extends RootBase {
read (path: string[]): Node {
const segmentName = path.shift() as string
if (path.length === 0) {
// only the segment name was in the path so return a SegmentList
const segments = this.children.filter(x => (x as Segment).name === segmentName) as Segment[]
if (segments.length > 0) {
return new SegmentList(this, segments) as Node
Expand All @@ -108,7 +105,7 @@ export class Message extends RootBase {
return segment.read(path)
}
}
throw new HL7FatalError(500, 'Unable to process the read function correctly.')
return Message.empty
}

/**
Expand Down Expand Up @@ -152,26 +149,27 @@ export class Message extends RootBase {
}

/** @internal */
private _getFirstSegment (name: string): Segment {
private _getFirstSegment (name: string): Segment | undefined {
const children = this.children
for (let i = 0, l = children.length; i < l; i++) {
const segment = children[i] as Segment
if (segment.name === name) {
return segment
}
}
throw new HL7FatalError(500, 'Unable to process _getFirstSegment.')
return undefined
// throw new HL7FatalError(500, 'Unable to process _getFirstSegment.')
}

/** @internal */
private _getFirstSegmentIndex (name: string): number {
private _getFirstSegmentIndex (name: string): number | undefined {
const children = this.children
for (let i = 0, l = children.length; i < l; i++) {
const segment = children[i] as Segment
if (segment.name === name) {
return i
}
}
return 0
return undefined
}
}
20 changes: 10 additions & 10 deletions src/builder/modules/emptyNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Node } from '../interface/node'
/** @internal */
export class EmptyNode implements Node {
get name (): string {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}

get length (): number {
Expand All @@ -23,15 +23,15 @@ export class EmptyNode implements Node {
}

forEach (_callback: (value: Node, index: number) => void): void {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}

toString (): string {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}

toRaw (): string {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}

toArray (): Node[] {
Expand All @@ -43,30 +43,30 @@ export class EmptyNode implements Node {
}

toDate (): Date {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}

toInteger (): number {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}

toFloat (): number {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}

toBoolean (): boolean {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}

read (_path: string[]): Node {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}

write (_path: string[], _value: string): Node {
return this
}

get path (): string[] {
throw new Error('Not implemented')
throw new Error('Method not implemented')
}
}
3 changes: 2 additions & 1 deletion src/builder/modules/field.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { HL7FatalError } from '../../utils/exception'
import { Delimiters } from '../decorators/delimiters'
import { Node } from '../interface/node'
import { FieldRepetition } from './fieldRepetition'
Expand Down Expand Up @@ -29,7 +30,7 @@ export class Field extends ValueNode {
if (this.children.length > 0) {
return this.children[0].read(path)
}
throw new Error('We have a problem.')
throw new HL7FatalError(500, 'We have a problem.')
}

/**
Expand Down
Loading

0 comments on commit 65f09a1

Please sign in to comment.