Skip to content

Commit

Permalink
Merge pull request #89 from nrkno/feat/mosObj
Browse files Browse the repository at this point in the history
fix!: proper support for Profile 1 <mosReqAll>, <mosObj> and <mosListAll> (SOFIE-2890)
  • Loading branch information
nytamin committed Feb 2, 2024
2 parents a87681f + 34fba90 commit 70441b4
Show file tree
Hide file tree
Showing 7 changed files with 504 additions and 18 deletions.
38 changes: 27 additions & 11 deletions packages/connector/src/MosDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ export class MosDevice implements IMOSDevice {

// Callbacks for Profile 1:
private _callbackOnRequestMOSOBject?: (objId: string) => Promise<IMOSObject | null>
private _callbackOnRequestAllMOSObjects?: () => Promise<Array<IMOSObject>>
private _callbackOnRequestAllMOSObjects?: () => Promise<IMOSObject[]>
private _callbackOnMOSObjects?: (objs: IMOSObject[]) => Promise<IMOSAck>

// Callbacks for Profile 2:
private _callbackOnCreateRunningOrder?: (ro: IMOSRunningOrder) => Promise<IMOSROAck>
Expand Down Expand Up @@ -306,6 +307,15 @@ export class MosDevice implements IMOSDevice {
},
this.strict
)
} else if (data.mosObj && typeof this._callbackOnMOSObjects === 'function') {
const obj = MosModel.XMLMosObject.fromXML(data.mosObj, this.strict)
const resp = await this._callbackOnMOSObjects([obj])
return new MosModel.MOSAck(resp, this.strict)
} else if (data.mosListAll && typeof this._callbackOnMOSObjects === 'function') {
const mosObjs = Array.isArray(data.mosListAll.mosObj) ? data.mosListAll.mosObj : [data.mosListAll.mosObj]
const objs = mosObjs.map((mosObj: any) => MosModel.XMLMosObject.fromXML(mosObj, this.strict))
const resp = await this._callbackOnMOSObjects(objs)
return new MosModel.MOSAck(resp, this.strict)
}
// Profile 2: -------------------------------------------------------------------------------------------------
// Translate deprecated messages into the functionally equivalent roElementActions:
Expand Down Expand Up @@ -855,17 +865,22 @@ export class MosDevice implements IMOSDevice {
this.checkProfile('onRequestAllMOSObjects', 'profile1')
this._callbackOnRequestAllMOSObjects = cb
}
onMOSObjects(cb: (objs: IMOSObject[]) => Promise<IMOSAck>): void {
this.checkProfile('onMOSObjects', 'profile1')
this._callbackOnMOSObjects = cb
}

async sendRequestAllMOSObjects(): Promise<Array<IMOSObject>> {
const message = new MosModel.ReqMosObjAll(undefined, this.strict)
const reply = await this.executeCommand(message)
if (reply.mos.roAck) {
throw new Error(MosModel.XMLMosROAck.fromXML(reply.mos.roAck, this.strict).toString())
} else if (reply.mos.mosListAll) {
return this.handleParseReply(() => MosModel.XMLMosObjects.fromXML(reply.mos.mosListAll.mosObj, this.strict))
} else {
throw new Error(`Unknown response: ${safeStringify(reply).slice(0, 200)}`)
async sendRequestAllMOSObjects(pause?: number): Promise<IMOSAck> {
if (typeof this._callbackOnMOSObjects !== 'function') {
throw new Error('Cannot sent request, because callback onMOSObjects() is required')
}

const message = new MosModel.ReqMosObjAll(pause, this.strict)
const reply = await this.executeCommand(message)

return this.handleParseReply((strict) => MosModel.XMLMosAck.fromXML(reply.mos.mosAck, strict))
// Then we'll be sent mosListAll or mosObj messages separately,
// handled in the callback in this.onMOSObjects(cb)
}

/**
Expand All @@ -889,7 +904,7 @@ export class MosDevice implements IMOSDevice {
return this.sendRequestMOSObject(objId)
}
/** @deprecated getAllMOSObjects is deprecated, use sendRequestAllMOSObjects instead */
async getAllMOSObjects(): Promise<IMOSObject[]> {
async getAllMOSObjects(): Promise<IMOSAck> {
return this.sendRequestAllMOSObjects()
}

Expand Down Expand Up @@ -1516,6 +1531,7 @@ export class MosDevice implements IMOSDevice {
requireProfile(1, 0)
requireMOSCallback('1', '_callbackOnRequestMOSOBject', this.onRequestMOSObject)
requireMOSCallback('1', '_callbackOnRequestAllMOSObjects', this.onRequestAllMOSObjects)
requireMOSCallback('1', '_callbackOnMOSObjects', this.onMOSObjects)
}
if (this.supportedProfiles.profile2) {
requireProfile(2, 0)
Expand Down
14 changes: 14 additions & 0 deletions packages/connector/src/__tests__/Profile0.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
getMosConnection,
getMosDevice,
getXMLReply,
mosTypes,
setupMocks,
} from './lib'
import { MosConnection, MosDevice, IMOSObject, IMOSListMachInfo } from '..'
Expand All @@ -20,6 +21,7 @@ import { xmlData, xmlApiData } from '../__mocks__/testData'
/* eslint-disable @typescript-eslint/no-unused-vars */
// @ts-ignore imports are unused
import { Socket } from 'net'
import { IMOSAck, IMOSAckStatus } from '@mos-connection/model'
/* eslint-enable @typescript-eslint/no-unused-vars */

beforeAll(() => {
Expand All @@ -43,6 +45,7 @@ describe('Profile 0', () => {
let onRequestMachineInfo: jest.Mock<any, any>
let onRequestMOSObject: jest.Mock<any, any>
let onRequestAllMOSObjects: jest.Mock<any, any>
let onMOSObjects: jest.Mock<any, any>

beforeAll(async () => {
mosConnection = await getMosConnection(
Expand Down Expand Up @@ -74,6 +77,17 @@ describe('Profile 0', () => {
mosDevice.onRequestAllMOSObjects(async (): Promise<Array<IMOSObject>> => {
return onRequestAllMOSObjects()
})
onMOSObjects = jest.fn(async (): Promise<IMOSAck> => {
return {
ID: mosTypes.mosString128.create(''),
Revision: 1,
Status: IMOSAckStatus.ACK,
Description: mosTypes.mosString128.create(''),
}
})
mosDevice.onMOSObjects(async (objs: IMOSObject[]): Promise<IMOSAck> => {
return onMOSObjects(objs)
})
const b = doBeforeAll()
socketMockLower = b.socketMockLower
socketMockUpper = b.socketMockUpper
Expand Down
67 changes: 63 additions & 4 deletions packages/connector/src/__tests__/Profile1.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import {
IMOSObjectStatus,
IMOSObjectAirStatus,
IMOSObjectPathType,
IMOSAck,
IMOSAckStatus,
} from '..'
import { SocketMock } from '../__mocks__/socket'
import { xmlData, xmlApiData } from '../__mocks__/testData'
Expand Down Expand Up @@ -57,6 +59,8 @@ describe('Profile 1', () => {
let onRequestMachineInfo: jest.Mock<any, any>
let onRequestMOSObject: jest.Mock<any, any>
let onRequestAllMOSObjects: jest.Mock<any, any>
let onMOSObjects: jest.Mock<any, any>
let receivedMosObjects: Array<IMOSObject> = []

beforeAll(async () => {
mosConnection = await getMosConnection(
Expand Down Expand Up @@ -88,6 +92,19 @@ describe('Profile 1', () => {
mosDevice.onRequestAllMOSObjects(async (): Promise<Array<IMOSObject>> => {
return onRequestAllMOSObjects()
})
onMOSObjects = jest.fn(async (objs: IMOSObject[]): Promise<IMOSAck> => {
receivedMosObjects.push(...objs)

return {
ID: mosTypes.mosString128.create(''),
Revision: 1,
Status: IMOSAckStatus.ACK,
Description: mosTypes.mosString128.create(''),
}
})
mosDevice.onMOSObjects(async (objs: IMOSObject[]): Promise<IMOSAck> => {
return onMOSObjects(objs)
})
const b = doBeforeAll()
socketMockLower = b.socketMockLower
socketMockUpper = b.socketMockUpper
Expand All @@ -107,6 +124,8 @@ describe('Profile 1', () => {
// SocketMock.mockClear()
onRequestMOSObject.mockClear()
onRequestAllMOSObjects.mockClear()
onMOSObjects.mockClear()
receivedMosObjects.splice(0, 99999)

serverSocketMockLower.mockClear()
serverSocketMockUpper.mockClear()
Expand Down Expand Up @@ -257,25 +276,65 @@ describe('Profile 1', () => {
Status: 'ACK',
})
})
test('receive mosObj', async () => {
// Fake incoming message on socket:
await fakeIncomingMessage(serverSocketMockLower, xmlData.mosObj)
expect(onMOSObjects).toHaveBeenCalledTimes(1)
expect(onMOSObjects.mock.calls[0][0]).toHaveLength(1)
expect(fixSnapshot(onMOSObjects.mock.calls)).toMatchSnapshot()

// Check reply to socket server:
await serverSocketMockLower.mockWaitForSentMessages()
expect(serverSocketMockLower.mockSentMessage).toHaveBeenCalledTimes(1)
// @ts-ignore mock
const reply = decode(serverSocketMockLower.mockSentMessage.mock.calls[0][0])
const parsedReply: any = xml2js(reply, { compact: true, nativeType: true, trim: true })
expect(parsedReply.mos.mosAck).toBeTruthy()
expect(parsedReply).toMatchSnapshot()
})
test('receive mosListAll', async () => {
// Fake incoming message on socket:
await fakeIncomingMessage(serverSocketMockLower, xmlData.mosListAll)
expect(onMOSObjects).toHaveBeenCalledTimes(1)
expect(onMOSObjects.mock.calls[0][0]).toHaveLength(2)
expect(fixSnapshot(onMOSObjects.mock.calls)).toMatchSnapshot()

// Check reply to socket server:
await serverSocketMockLower.mockWaitForSentMessages()
expect(serverSocketMockLower.mockSentMessage).toHaveBeenCalledTimes(1)
// @ts-ignore mock
const reply = decode(serverSocketMockLower.mockSentMessage.mock.calls[0][0])
const parsedReply: any = xml2js(reply, { compact: true, nativeType: true, trim: true })
expect(parsedReply.mos.mosAck).toBeTruthy()
expect(parsedReply).toMatchSnapshot()
})
test('getAllMOSObjects', async () => {
expect(socketMockLower).toBeTruthy()

const REPLY_WAIT_TIME = 100
// Prepare mock server response:
const mockReply = jest.fn((data) => {
const str = decode(data)
const messageID = getMessageId(str)
const repl = getXMLReply(messageID, xmlData.mosListAll)
const repl = getXMLReply(messageID, xmlData.mosAck)

setTimeout(() => {
fakeIncomingMessage(serverSocketMockLower, xmlData.mosListAll).catch(console.error)
}, REPLY_WAIT_TIME)
return encode(repl)
})
socketMockLower.mockAddReply(mockReply)
const returnedObjs: Array<IMOSObject> = await mosDevice.sendRequestAllMOSObjects()
await mosDevice.sendRequestAllMOSObjects()

await delay(REPLY_WAIT_TIME + 100)

expect(mockReply).toHaveBeenCalledTimes(1)
const msg = decode(mockReply.mock.calls[0][0])
expect(msg).toMatch(/<mosReqAll>/)
checkMessageSnapshot(msg)

expect(returnedObjs).toMatchObject(xmlApiData.mosListAll)
expect(returnedObjs).toMatchSnapshot()
expect(receivedMosObjects).toMatchObject(xmlApiData.mosListAll)
expect(receivedMosObjects).toMatchSnapshot()
})

test(
Expand Down
17 changes: 17 additions & 0 deletions packages/connector/src/__tests__/Profile2.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { xml2js } from 'xml-js'
/* eslint-disable @typescript-eslint/no-unused-vars */
// @ts-ignore imports are unused
import { Socket } from 'net'
import { IMOSAck, IMOSAckStatus } from '@mos-connection/model'
/* eslint-enable @typescript-eslint/no-unused-vars */

beforeAll(() => {
Expand All @@ -66,6 +67,8 @@ describe('Profile 2', () => {
let onRequestMachineInfo: jest.Mock<any, any>
let onRequestMOSObject: jest.Mock<any, any>
let onRequestAllMOSObjects: jest.Mock<any, any>
let onMOSObjects: jest.Mock<any, any>

let onCreateRunningOrder: jest.Mock<any, any>
let onReplaceRunningOrder: jest.Mock<any, any>
let onDeleteRunningOrder: jest.Mock<any, any>
Expand Down Expand Up @@ -122,6 +125,20 @@ describe('Profile 2', () => {
mosDevice.onRequestAllMOSObjects(async (): Promise<Array<IMOSObject>> => {
return onRequestAllMOSObjects()
})
mosDevice.onRequestAllMOSObjects(async (): Promise<Array<IMOSObject>> => {
return onRequestAllMOSObjects()
})
onMOSObjects = jest.fn(async (): Promise<IMOSAck> => {
return {
ID: mosTypes.mosString128.create(''),
Revision: 1,
Status: IMOSAckStatus.ACK,
Description: mosTypes.mosString128.create(''),
}
})
mosDevice.onMOSObjects(async (objs: IMOSObject[]): Promise<IMOSAck> => {
return onMOSObjects(objs)
})

// Profile 2:
const roAckReply = async () => {
Expand Down
Loading

0 comments on commit 70441b4

Please sign in to comment.