Skip to content

Commit

Permalink
v3 request reply support
Browse files Browse the repository at this point in the history
  • Loading branch information
GreenRover committed Apr 3, 2023
1 parent f804bdb commit 39219fd
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/models/operation-reply-address.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { BaseModel } from './base';
import type { DescriptionMixinInterface, ExtensionsMixinInterface } from './mixins';

export interface OperationReplyAddressInterface extends BaseModel, DescriptionMixinInterface, ExtensionsMixinInterface {
hasLocation(): boolean;
location(): string | undefined;
}

13 changes: 13 additions & 0 deletions src/models/operation-reply.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { BaseModel } from './base';
import { ChannelInterface } from './channel';
import { MessagesInterface } from './messages';
import type { ExtensionsMixinInterface } from './mixins';
import { OperationReplyAddressInterface } from './operation-reply-address';

export interface OperationReplyInterface extends BaseModel, ExtensionsMixinInterface {
hasAddress(): boolean;
address(): OperationReplyAddressInterface | undefined,
hasChannel(): boolean;
channel(): ChannelInterface | undefined;
messages(): MessagesInterface;
}
3 changes: 3 additions & 0 deletions src/models/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { OperationTraitInterface } from './operation-trait';
import type { ChannelsInterface } from './channels';
import type { ServersInterface } from './servers';
import type { MessagesInterface } from './messages';
import { OperationReplyInterface } from './operation-reply';

export type OperationAction = 'send' | 'receive' | 'publish' | 'subscribe';

Expand All @@ -15,4 +16,6 @@ export interface OperationInterface extends BaseModel, OperationTraitInterface {
channels(): ChannelsInterface
messages(): MessagesInterface;
traits(): OperationTraitsInterface;
hasReply(): boolean;
reply(): OperationReplyInterface | undefined;
}
28 changes: 28 additions & 0 deletions src/models/v3/operation-reply-address.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { BaseModel } from '../base';
import { ExtensionsInterface } from 'models/extensions';
import { OperationReplyAddressInterface } from 'models/operation-reply-address';
import { description, extensions, hasDescription } from './mixins';

import type { v3 } from '../../spec-types';

export class OperationReplyAddress<T extends Record<string, any> = Record<string, any>> extends BaseModel<v3.OperationReplyAddressObject & T, { protocol: string }> implements OperationReplyAddressInterface {
hasLocation(): boolean {
return !!this._json.location;
}

location(): string | undefined {
return this._json.location;
}

hasDescription(): boolean {
return hasDescription(this);
}

description(): string | undefined {
return description(this);
}

extensions(): ExtensionsInterface {
return extensions(this);
}
}
46 changes: 46 additions & 0 deletions src/models/v3/operation-reply.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { BaseModel } from '../base';
import { ChannelInterface } from 'models/channel';
import { ExtensionsInterface } from 'models/extensions';
import { MessagesInterface } from 'models/messages';
import { OperationReplyInterface } from 'models/operation-reply';
import { OperationReplyAddressInterface } from 'models/operation-reply-address';
import { Messages } from '../messages';
import { Channel } from './channel';
import { Message } from './message';

import type { v3 } from '../../spec-types';
import { OperationReplyAddress } from './operation-reply-address';

import { extensions } from './mixins';

export class OperationReply<T extends Record<string, any> = Record<string, any>> extends BaseModel<v3.OperationReplyObject & T, { protocol: string }> implements OperationReplyInterface {
hasAddress(): boolean {
return !!this._json.address;
}

address(): OperationReplyAddressInterface | undefined {
if (!this._json.address) return undefined;
return new OperationReplyAddress(this._json.address);
}

hasChannel(): boolean {
return !!this._json.channel;
}

channel(): ChannelInterface | undefined {
if (!this._json.channel) return undefined;
return this.createModel(Channel, this._json.channel as v3.ChannelObject, { id: '', pointer: this.jsonPath('channel') });
}

messages(): MessagesInterface {
return new Messages(
Object.entries(this._json.messages || {}).map(([messageName, message]) => {
return this.createModel(Message, message, { id: messageName, pointer: this.jsonPath(`messages/${messageName}`) });
})
);
}

extensions(): ExtensionsInterface {
return extensions(this);
}
}
11 changes: 11 additions & 0 deletions src/models/v3/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import type { ServersInterface } from '../servers';
import type { ServerInterface } from '../server';

import type { v3 } from '../../spec-types';
import { OperationReplyInterface } from 'models/operation-reply';
import { OperationReply } from './operation-reply';

export class Operation extends OperationTrait<v3.OperationObject> implements OperationInterface {
action(): OperationAction {
Expand Down Expand Up @@ -66,4 +68,13 @@ export class Operation extends OperationTrait<v3.OperationObject> implements Ope
})
);
}

hasReply(): boolean {
return !!this._json.reply;
}

reply(): OperationReplyInterface | undefined {
if (!this._json.reply) return undefined;
return new OperationReply(this._json.reply);
}
}
12 changes: 12 additions & 0 deletions src/spec-types/v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export interface OperationObject extends SpecificationExtensions {
externalDocs?: ExternalDocumentationObject;
bindings?: OperationBindingsObject | ReferenceObject;
traits?: OperationTraitObject[];
reply?: OperationReplyObject;
}

export interface OperationTraitObject extends SpecificationExtensions {
Expand Down Expand Up @@ -150,6 +151,17 @@ export interface OperationBindingsObject extends SpecificationExtensions {
ibmmq?: Binding;
}

export interface OperationReplyObject extends SpecificationExtensions {
address?: OperationReplyAddressObject;
channel?: ChannelObject | ReferenceObject;
messages?: MessagesObject;
}

export interface OperationReplyAddressObject extends SpecificationExtensions {
location: string;
description?: string;
}

export type MessagesObject = Record<string, MessageObject>;

export interface MessageObject extends MessageTraitObject, SpecificationExtensions {
Expand Down
40 changes: 40 additions & 0 deletions test/models/v3/operation-reply-address.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { OperationReplyAddress } from '../../../src/models/v3/operation-reply-address';
import { assertDescription, assertExtensions, serializeInput } from './utils';

import type { v3 } from '../../../src/spec-types';

describe('Operation reply address model', function () {

describe('.hasLocation()', function () {
it('should return true when there is a value', function () {
const doc = serializeInput<v3.OperationReplyAddressObject>({ location: '...' });
const d = new OperationReplyAddress(doc);
expect(d.hasLocation()).toEqual(true);
});

it('should return false when there is no value', function () {
const doc = serializeInput<v3.OperationReplyAddressObject>({});
const d = new OperationReplyAddress(doc);
expect(d.hasLocation()).toEqual(false);
});
});

describe('.location()', function () {
it('should return the value', function () {
const doc = serializeInput<v3.OperationReplyAddressObject>({ location: '...' });
const d = new OperationReplyAddress(doc);
expect(d.location()).toEqual(doc.location);
});

it('should return undefined when there is no value', function () {
const doc = serializeInput<v3.OperationReplyAddressObject>({});
const d = new OperationReplyAddress(doc);
expect(d.location()).toBeUndefined();
});
});

describe('mixins', function () {
assertExtensions(OperationReplyAddress);
assertDescription(OperationReplyAddress);
});
});
71 changes: 71 additions & 0 deletions test/models/v3/operation-reply.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { ModelMetadata } from '../../../src/models';
import { Channel } from '../../../src/models/v3/channel';
import { OperationReply } from '../../../src/models/v3/operation-reply';
import { OperationReplyAddress } from '../../../src/models/v3/operation-reply-address';
import { Messages } from '../../../src/models/messages';
import { Message } from '../../../src/models/v3/message';
import { serializeInput, assertExtensions } from './utils';

import type { v3 } from '../../../src/spec-types';

describe('Operation reply model', function () {

describe('.address()', function() {
it('should return undefined if address is not defined', function () {
const d = new OperationReply({ });
expect(d.hasAddress()).toBeFalsy();
expect(d.address()).toBeUndefined();
});

it('should return a Reply Address object ', function () {
const d = new OperationReply({ address: { location: '$message.header#/replyTo' } });
expect(d.hasAddress()).toBeTruthy();
expect(d.address()).toBeInstanceOf(OperationReplyAddress);
});
});

describe('.channel()', function() {
it('should return undefined if address is not defined', function () {
const d = new OperationReply({ });
expect(d.hasChannel()).toBeFalsy();
expect(d.channel()).toBeUndefined();
});

it('should return a Channel object ', function () {
const doc = serializeInput<v3.OperationReplyObject>({ channel: { $ref: 'test' } });
const d = new OperationReply(doc);
expect(d.hasChannel()).toBeTruthy();
expect(d.channel()).toBeInstanceOf(Channel);
});
});

describe('.messages()', function() {
it('should return collection of messages - single message', function() {
const d = new OperationReply({ messages: { someMessage: { messageId: 'messageId' } } });
expect(d.messages()).toBeInstanceOf(Messages);
expect(d.messages().all()).toHaveLength(1);
expect(d.messages().all()[0]).toBeInstanceOf(Message);
});

it('should return collection of messages - more than one messages', function() {
const d = new OperationReply({ messages: { someMessage1: { messageId: 'messageId1' }, someMessage2: { messageId: 'messageId2' } } });
expect(d.messages()).toBeInstanceOf(Messages);
expect(d.messages().all()).toHaveLength(2);
expect(d.messages().all()[0]).toBeInstanceOf(Message);
expect(d.messages().all()[0].messageId()).toEqual('messageId1');
expect(d.messages().all()[1]).toBeInstanceOf(Message);
expect(d.messages().all()[1].messageId()).toEqual('messageId2');
});

it('should return undefined when there is no value', function() {
const d = new OperationReply({ });
expect(d.messages()).toBeInstanceOf(Messages);
expect(d.messages().all()).toHaveLength(0);
});
});


describe('mixins', function () {
assertExtensions(OperationReply);
});
});
15 changes: 15 additions & 0 deletions test/models/v3/operation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Servers } from '../../../src/models/servers';
import { Server } from '../../../src/models/v3/server';

import { assertCoreModel } from './utils';
import { OperationReply } from '../../../src/models/v3/operation-reply';

describe('Operation model', function() {
describe('.id()', function() {
Expand Down Expand Up @@ -123,6 +124,20 @@ describe('Operation model', function() {
});
});

describe('.reply()', function() {
it('should return undefined if reply is not defined', function () {
const d = new Operation({ action: 'send', channel: {}, traits: [] });
expect(d.hasReply()).toBeFalsy();
expect(d.reply()).toBeUndefined();
});

it('should return a Reply object ', function () {
const d = new Operation({ action: 'send', channel: {}, reply: { address: { location: '$message.header#/replyTo' }} });
expect(d.hasReply()).toBeTruthy();
expect(d.reply()).toBeInstanceOf(OperationReply);
});
});

describe('mixins', function() {
assertCoreModel(Operation);
});
Expand Down

0 comments on commit 39219fd

Please sign in to comment.