From 4e39f0fa66feb99d020c48ab480d2b15070b5966 Mon Sep 17 00:00:00 2001 From: Sergio Moya <1083296+smoya@users.noreply.github.com> Date: Wed, 31 Aug 2022 12:25:41 +0200 Subject: [PATCH 1/6] refactor: adapt components to parser-api --- src/models/components.ts | 42 +++--- src/models/correlation-ids.ts | 4 + src/models/v2/channel.ts | 4 +- src/models/v2/components.ts | 104 +++++++++------ src/models/v2/correlation-ids.ts | 14 ++ test/models/v2/components.spec.ts | 204 ++++++++++++++++++------------ 6 files changed, 231 insertions(+), 141 deletions(-) create mode 100644 src/models/correlation-ids.ts create mode 100644 src/models/v2/correlation-ids.ts diff --git a/src/models/components.ts b/src/models/components.ts index 0da724b2d..ff57f4cbe 100644 --- a/src/models/components.ts +++ b/src/models/components.ts @@ -1,28 +1,30 @@ import type { BaseModel } from './base'; -import type { ServerInterface } from './server'; -import type { ChannelInterface } from './channel'; -import type { OperationTraitInterface } from './operation-trait'; -import type { MessageInterface } from './message'; -import type { MessageTraitInterface } from './message-trait'; -import type { SchemaInterface } from './schema'; -import type { ChannelParameterInterface } from './channel-parameter'; -import type { ServerVariableInterface } from './server-variable'; -import type { CorrelationIdInterface } from './correlation-id'; import type { BindingsInterface } from './bindings'; -import type { SecuritySchemeInterface } from './security-scheme'; import type { ExtensionsMixinInterface } from './mixins'; +import type { ServersInterface } from './servers'; +import type { ChannelsInterface } from './channels'; +import type { MessagesInterface } from './messages'; +import type { SchemasInterface } from './schemas'; +import type { ChannelParametersInterface } from './channel-parameters'; +import type { ServerVariablesInterface } from './server-variables'; +import type { OperationTraitsInterface } from './operation-traits'; +import type { MessageTraitsInterface } from './message-traits'; +import type { SecuritySchemesInterface } from './security-schemes'; +import type { CorrelationIdsInterface } from './correlation-ids'; +import type { OperationsInterface } from './operations'; export interface ComponentsInterface extends BaseModel, ExtensionsMixinInterface { - servers(): Record; - channels(): Record; - messages(): Record; - schemas(): Record; - channelParameters(): Record; - serverVariables(): Record; - operationTraits(): Record; - messageTraits(): Record; - correlationIds(): Record; - securitySchemes(): Record; + servers(): ServersInterface; + channels(): ChannelsInterface; + messages(): MessagesInterface; + schemas(): SchemasInterface; + channelParameters(): ChannelParametersInterface; + serverVariables(): ServerVariablesInterface; + operations(): OperationsInterface; + operationTraits(): OperationTraitsInterface; + messageTraits(): MessageTraitsInterface; + correlationIds(): CorrelationIdsInterface; + securitySchemes(): SecuritySchemesInterface; serverBindings(): Record; channelBindings(): Record; operationBindings(): Record; diff --git a/src/models/correlation-ids.ts b/src/models/correlation-ids.ts new file mode 100644 index 000000000..1c2db2c6b --- /dev/null +++ b/src/models/correlation-ids.ts @@ -0,0 +1,4 @@ +import type { Collection } from './collection'; +import type { CorrelationIdInterface } from './correlation-id'; + +export interface CorrelationIdsInterface extends Collection { } \ No newline at end of file diff --git a/src/models/v2/channel.ts b/src/models/v2/channel.ts index 28102db42..ba1c031c5 100644 --- a/src/models/v2/channel.ts +++ b/src/models/v2/channel.ts @@ -21,6 +21,7 @@ import type { ServersInterface } from "../servers"; import type { ServerInterface } from "../server"; import type { v2 } from "../../spec-types"; +import { OperationObject } from "spec-types/v2"; export class Channel extends BaseModel implements ChannelInterface { id(): string { @@ -53,8 +54,9 @@ export class Channel extends BaseModel { + let id = this._json[operationAction as 'publish' | 'subscribe'] && (this._json[operationAction as 'publish' | 'subscribe'] as OperationObject).operationId || this.meta().id + "_" + operationAction; this._json[operationAction as 'publish' | 'subscribe'] && operations.push( - this.createModel(Operation, this._json[operationAction as 'publish' | 'subscribe'], { id: operationAction, action: operationAction, pointer: `${this._meta.pointer}/${operationAction}` }), + this.createModel(Operation, this._json[operationAction as 'publish' | 'subscribe'], { id: id, action: operationAction, pointer: `${this._meta.pointer}/${operationAction}` }), ); }); return new Operations(operations); diff --git a/src/models/v2/components.ts b/src/models/v2/components.ts index e14b50f81..e4d72586a 100644 --- a/src/models/v2/components.ts +++ b/src/models/v2/components.ts @@ -4,72 +4,94 @@ import { Binding } from "./binding"; import { Channel } from "./channel"; import { ChannelParameter } from "./channel-parameter"; import { CorrelationId } from "./correlation-id"; -import { Message } from "./message"; import { MessageTrait } from "./message-trait"; import { OperationTrait } from "./operation-trait"; import { Schema } from "./schema"; import { SecurityScheme } from "./security-scheme"; import { Server } from "./server"; import { ServerVariable } from "./server-variable"; - import { extensions } from './mixins'; - import type { BindingsInterface } from "../bindings"; import type { ComponentsInterface } from "../components"; -import type { ChannelInterface } from "../channel"; -import type { ChannelParameterInterface } from "../channel-parameter"; -import type { CorrelationIdInterface } from "../correlation-id"; import type { ExtensionsInterface } from "../extensions"; -import type { MessageInterface } from "../message"; -import type { MessageTraitInterface } from "../message-trait"; -import type { OperationTraitInterface } from "../operation-trait"; -import type { SchemaInterface } from "../schema"; -import type { SecuritySchemeInterface } from "../security-scheme"; -import type { ServerInterface } from "../server"; -import type { ServerVariableInterface } from "../server-variable"; import type { Constructor } from "../utils"; - +import type { ServersInterface } from "models/servers"; +import { Servers } from "./servers"; +import { Channels } from "./channels"; +import type { ChannelsInterface } from "models/channels"; +import type { MessagesInterface } from "models/messages"; +import type { SchemasInterface } from "models/schemas"; +import type { ChannelParametersInterface } from "models/channel-parameters"; +import type { ServerVariablesInterface } from "models/server-variables"; +import type { OperationTraitsInterface } from "models/operation-traits"; +import type { SecuritySchemesInterface } from "models/security-schemes"; +import { Messages } from "./messages"; +import { Schemas } from "./schemas"; +import { ChannelParameters } from "./channel-parameters"; +import { ServerVariables } from "./server-variables"; +import { OperationTraits } from "./operation-traits"; +import { MessageTraits } from "./message-traits"; +import type { MessageTraitsInterface } from "models/message-traits"; +import { SecuritySchemes } from "./security-schemes"; +import { Collection } from "models/collection"; +import { CorrelationIds } from "./correlation-ids"; +import { tilde } from '../../utils'; +import type { OperationsInterface } from "models/operations"; +import type { OperationInterface } from "models/operation"; +import { Operations } from "./operations"; +import { Message } from "./message"; import type { v2 } from "../../spec-types"; +import { ComponentsObject } from "spec-types/v2"; export class Components extends BaseModel implements ComponentsInterface { - servers(): Record { - return this.createMap('servers', Server); + servers(): ServersInterface { + return this.createCollection('servers', Servers, Server); + } + + channels(): ChannelsInterface { + return new Channels( + Object.entries(this._json.channels || {}).map(([channelAddress, channel]) => + this.createModel(Channel, channel, { id: channelAddress, address: channelAddress, pointer: `/components/channels/${tilde(channelAddress)}` }) + ) + ); } - channels(): Record { - return this.createMap('channels', Channel); + messages(): MessagesInterface { + return this.createCollection('messages', Messages, Message); } - messages(): Record { - return this.createMap('messages', Message); + schemas(): SchemasInterface { + return this.createCollection('schemas', Schemas, Schema); } - schemas(): Record { - return this.createMap('schemas', Schema); + channelParameters(): ChannelParametersInterface { + return this.createCollection('parameters', ChannelParameters, ChannelParameter); } - channelParameters(): Record { - return this.createMap('parameters', ChannelParameter); + serverVariables(): ServerVariablesInterface { + return this.createCollection('serverVariables', ServerVariables, ServerVariable); } - serverVariables(): Record { - return this.createMap('serverVariables', ServerVariable); + operations(): OperationsInterface { + const operations: OperationInterface[] = []; + this.channels().forEach(channel => operations.push(...channel.operations().all())); + return new Operations(operations); } - operationTraits(): Record { - return this.createMap('operationTraits', OperationTrait); + operationTraits(): OperationTraitsInterface { + return this.createCollection('operationTraits', OperationTraits, OperationTrait); } - messageTraits(): Record { - return this.createMap('messageTraits', MessageTrait); + messageTraits(): MessageTraitsInterface { + return this.createCollection('messageTraits', MessageTraits, MessageTrait); } - correlationIds(): Record { - return this.createMap('correlationIds', CorrelationId); + correlationIds(): CorrelationIds { + return this.createCollection('correlationIds', CorrelationIds, CorrelationId); } - securitySchemes(): Record { - return this.createMap('securitySchemes', SecurityScheme); + securitySchemes(): SecuritySchemesInterface { + return this.createCollection('securitySchemes', SecuritySchemes, SecurityScheme); } serverBindings(): Record { @@ -92,11 +114,13 @@ export class Components extends BaseModel implements Compon return extensions(this); } - protected createMap(itemsName: keyof v2.ComponentsObject, model: Constructor): Record { - return Object.entries(this._json[itemsName] || {}).reduce((items, [itemName, item]) => { - items[itemName] = this.createModel(model, item, { id: itemName, pointer: `/components/${itemsName}/${itemName}` }) - return items; - }, {} as Record); + protected createCollection, T extends BaseModel>(itemsName: keyof ComponentsObject, collectionModel: Constructor, itemModel: Constructor): M { + let collectionItems: T[] = []; + Object.entries(this._json[itemsName] || {}).forEach(([itemName, item]) => { + collectionItems.push(this.createModel(itemModel, item, { id: itemName, pointer: `/components/${itemsName}/${itemName}` })) + }); + + return new collectionModel(collectionItems); } protected createBindings(itemsName: 'serverBindings' | 'channelBindings' | 'operationBindings' | 'messageBindings'): Record { @@ -107,6 +131,6 @@ export class Components extends BaseModel implements Compon ) ); return bindings; - }, {} as Record); + }, {} as Record); } } diff --git a/src/models/v2/correlation-ids.ts b/src/models/v2/correlation-ids.ts new file mode 100644 index 000000000..9d73eccb3 --- /dev/null +++ b/src/models/v2/correlation-ids.ts @@ -0,0 +1,14 @@ +import { Collection } from '../collection'; + +import type { CorrelationIdsInterface } from '../correlation-ids'; +import type { CorrelationIdInterface } from '../correlation-id'; + +export class CorrelationIds extends Collection implements CorrelationIdsInterface { + override get(id: string): CorrelationIdInterface | undefined { + return this.collections.find(correlationId => correlationId.meta()["key"] === id); + } + + override has(id: string): boolean { + return this.collections.some(correlationId => correlationId.meta()["key"] === id); + } +} diff --git a/test/models/v2/components.spec.ts b/test/models/v2/components.spec.ts index c550f7a1f..0abe25dd1 100644 --- a/test/models/v2/components.spec.ts +++ b/test/models/v2/components.spec.ts @@ -10,189 +10,222 @@ import { Schema } from '../../../src/models/v2/schema'; import { Server } from '../../../src/models/v2/server'; import { ServerVariable } from '../../../src/models/v2/server-variable'; import { SecurityScheme } from '../../../src/models/v2/security-scheme'; - +import { BaseModel, ModelMetadata } from '../../../src/models'; +import { Servers } from '../../../src/models/v2/servers'; +import { Channels } from '../../../src/models/v2/channels'; +import { Messages } from '../../../src/models/v2/messages'; +import { Collection } from '../../../src/models/collection'; +import { Constructor } from '../../../src/models/utils'; +import { Schemas } from '../../../src/models/v2/schemas'; +import { ChannelParameters } from '../../../src/models/v2/channel-parameters'; +import { ServerVariables } from '../../../src/models/v2/server-variables'; +import { OperationTraits } from '../../../src/models/v2/operation-traits'; +import { MessageTraits } from '../../../src/models/v2/message-traits'; +import { CorrelationIds } from '../../../src/models/v2/correlation-ids'; +import { SecuritySchemes } from '../../../src/models/v2/security-schemes'; +import { Operation } from '../../../src/models/v2/operation'; +import { Operations } from '../../../src/models/v2/operations'; +import { OperationAction } from '../../../src/models/operation'; import { serializeInput, assertExtensions } from './utils'; - import type { v2 } from '../../../src/spec-types'; +import { ChannelObject } from '../../../src/spec-types/v2'; describe('Components model', function() { describe('.servers()', function() { - it('should return map of servers', function() { + it('should return Servers with Server Object', function() { const doc = serializeInput({ servers: { server: {} } }); + const d = new Components(doc); - expect(typeof d.servers()).toEqual('object'); - expect(Object.keys(d.servers())).toHaveLength(1); - expect(d.servers()['server']).toBeInstanceOf(Server); + testCollection(doc, d.servers(), "servers", Servers, Server); }); - it('should return empty map when servers are not defined', function() { + it('should return Servers with empty server objects when servers are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.servers()).toEqual('object'); - expect(Object.keys(d.servers())).toHaveLength(0); + const items = d.servers(); + expect(items).toBeInstanceOf(Servers); + expect(items.all()).toHaveLength(0); }); }); describe('.channels()', function() { - it('should return map of channels', function() { + it('should return Channels with Channel Object', function() { const doc = serializeInput({ channels: { channel: {} } }); const d = new Components(doc); - expect(typeof d.channels()).toEqual('object'); - expect(Object.keys(d.channels())).toHaveLength(1); - expect(d.channels()['channel']).toBeInstanceOf(Channel); + const items = d.channels(); + expect(items).toBeInstanceOf(Channels); + expect(items.all()).toEqual([ + new Channel(doc.channels?.channel as ChannelObject, {id: "channel", address: "channel", pointer: "/components/channels/channel"} as ModelMetadata & { id: string, address: string } | undefined) + ]); }); - it('should return empty map when channels are not defined', function() { + + it('should return Channels with empty channel objects when channels are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.channels()).toEqual('object'); - expect(Object.keys(d.channels())).toHaveLength(0); + const items = d.channels(); + expect(items).toBeInstanceOf(Channels); + expect(items.all()).toHaveLength(0); }); }); describe('.messages()', function() { - it('should return map of messages', function() { + it('should return Messages with Message Object', function() { const doc = serializeInput({ messages: { message: {} } }); const d = new Components(doc); - expect(typeof d.messages()).toEqual('object'); - expect(Object.keys(d.messages())).toHaveLength(1); - expect(d.messages()['message']).toBeInstanceOf(Message); + testCollection(doc, d.messages(), "messages", Messages, Message); }); - it('should return empty map when messages are not defined', function() { + it('should return Messages with empty message objects when messages are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.messages()).toEqual('object'); - expect(Object.keys(d.messages())).toHaveLength(0); + const items = d.messages(); + expect(items).toBeInstanceOf(Messages); + expect(items.all()).toHaveLength(0); }); }); describe('.schemas()', function() { - it('should return map of schemas', function() { + it('should return Schemas with Schema Object', function() { const doc = serializeInput({ schemas: { schema: {} } }); const d = new Components(doc); - expect(typeof d.schemas()).toEqual('object'); - expect(Object.keys(d.schemas())).toHaveLength(1); - expect(d.schemas()['schema']).toBeInstanceOf(Schema); + testCollection(doc, d.schemas(), "schemas", Schemas, Schema); }); - it('should return empty map when schemas are not defined', function() { + it('should return Schemas with empty schema objects when schemas are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.schemas()).toEqual('object'); - expect(Object.keys(d.schemas())).toHaveLength(0); + const items = d.schemas(); + expect(items).toBeInstanceOf(Schemas); + expect(items.all()).toHaveLength(0); }); }); describe('.channelParameters()', function() { - it('should return map of channelParameters', function() { + it('should return ChannelParameters with ChannelParameter Object', function() { const doc = serializeInput({ parameters: { parameter: {} } }); const d = new Components(doc); - expect(typeof d.channelParameters()).toEqual('object'); - expect(Object.keys(d.channelParameters())).toHaveLength(1); - expect(d.channelParameters()['parameter']).toBeInstanceOf(ChannelParameter); + testCollection(doc, d.channelParameters(), "parameters", ChannelParameters, ChannelParameter); }); - it('should return empty map when channelParameters are not defined', function() { + it('should return Schemas with empty schema objects when schemas are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.channelParameters()).toEqual('object'); - expect(Object.keys(d.channelParameters())).toHaveLength(0); + const items = d.channelParameters(); + expect(items).toBeInstanceOf(ChannelParameters); + expect(items.all()).toHaveLength(0); }); }); describe('.serverVariables()', function() { - it('should return map of serverVariables', function() { + it('should return ServerVariables with ServerVariable Object', function() { const doc = serializeInput({ serverVariables: { variable: {} } }); const d = new Components(doc); - expect(typeof d.serverVariables()).toEqual('object'); - expect(Object.keys(d.serverVariables())).toHaveLength(1); - expect(d.serverVariables()['variable']).toBeInstanceOf(ServerVariable); + testCollection(doc, d.serverVariables(), "serverVariables", ServerVariables, ServerVariable); }); - it('should return empty map when serverVariables are not defined', function() { + it('should return ServerVariables with empty serverVariable objects when serverVariables are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.serverVariables()).toEqual('object'); - expect(Object.keys(d.serverVariables())).toHaveLength(0); + const items = d.serverVariables(); + expect(items).toBeInstanceOf(ServerVariables); + expect(items.all()).toHaveLength(0); }); }); describe('.operationTraits()', function() { - it('should return map of operationTraits', function() { + it('should return OperationTraits with OperationTrait Object', function() { const doc = serializeInput({ operationTraits: { trait: {} } }); const d = new Components(doc); - expect(typeof d.operationTraits()).toEqual('object'); - expect(Object.keys(d.operationTraits())).toHaveLength(1); - expect(d.operationTraits()['trait']).toBeInstanceOf(OperationTrait); + testCollection(doc, d.operationTraits(), "operationTraits", OperationTraits, OperationTrait); }); - it('should return empty map when operationTraits are not defined', function() { + it('should return OperationTraits with empty operationTrait objects when operationTraits are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.operationTraits()).toEqual('object'); - expect(Object.keys(d.operationTraits())).toHaveLength(0); + const items = d.operationTraits(); + expect(items).toBeInstanceOf(OperationTraits); + expect(items.all()).toHaveLength(0); }); }); describe('.messageTraits()', function() { - it('should return map of messageTraits', function() { + it('should return MessageTraits with MessageTrait Object', function() { const doc = serializeInput({ messageTraits: { trait: {} } }); const d = new Components(doc); - expect(typeof d.messageTraits()).toEqual('object'); - expect(Object.keys(d.messageTraits())).toHaveLength(1); - expect(d.messageTraits()['trait']).toBeInstanceOf(MessageTrait); + testCollection(doc, d.messageTraits(), "messageTraits", MessageTraits, MessageTrait); }); - it('should return empty map when messageTraits are not defined', function() { + it('should return MessageTraits with empty messageTrait objects when messageTraits are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.messageTraits()).toEqual('object'); - expect(Object.keys(d.messageTraits())).toHaveLength(0); + const items = d.messageTraits(); + expect(items).toBeInstanceOf(MessageTraits); + expect(items.all()).toHaveLength(0); }); }); describe('.correlationIds()', function() { - it('should return map of correlationIds', function() { + it('should return CorrelationIds with CorrelationId Object', function() { const doc = serializeInput({ correlationIds: { id: {} } }); const d = new Components(doc); - expect(typeof d.correlationIds()).toEqual('object'); - expect(Object.keys(d.correlationIds())).toHaveLength(1); - expect(d.correlationIds()['id']).toBeInstanceOf(CorrelationId); + testCollection(doc, d.correlationIds(), "correlationIds", CorrelationIds, CorrelationId); }); - it('should return empty map when correlationIds are not defined', function() { + it('should return CorrelationIds with empty correlationId objects when correlationIds are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.correlationIds()).toEqual('object'); - expect(Object.keys(d.correlationIds())).toHaveLength(0); + const items = d.correlationIds(); + expect(items).toBeInstanceOf(CorrelationIds); + expect(items.all()).toHaveLength(0); + }); + }); + + describe('.operations()', function() { + it('should return Operations with Operation Object', function() { + const doc = { channels: { channel: { publish: {} } } }; + const d = new Components(doc); + let expectedOperations: Operation[] = [ + new Operation({}, {action: "publish", id: "channel_publish", "pointer": "/components/channels/channel/publish"} as ModelMetadata & { id: string, action: OperationAction } ) + ]; + + const operations = d.operations(); + expect(operations).toBeInstanceOf(Operations); + expect(operations.all()).toEqual(expectedOperations); + }); + + it('should return Operations with empty operation objects when operations are not defined in channels', function() { + const doc = { channels: { channel: {} } }; + const d = new Components(doc); + const operations = d.operations(); + expect(operations).toBeInstanceOf(Operations); + expect(operations.all()).toHaveLength(0); }); }); describe('.securitySchemes()', function() { - it('should return map of securitySchemes', function() { + it('should return SecuritySchemes with SecurityScheme Object', function() { const doc = serializeInput({ securitySchemes: { scheme: {} } }); const d = new Components(doc); - expect(typeof d.securitySchemes()).toEqual('object'); - expect(Object.keys(d.securitySchemes())).toHaveLength(1); - expect(d.securitySchemes()['scheme']).toBeInstanceOf(SecurityScheme); + testCollection(doc, d.securitySchemes(), "securitySchemes", SecuritySchemes, SecurityScheme); }); - it('should return empty map when securitySchemes are not defined', function() { + it('should return SecuritySchemes with empty securityScheme objects when securitySchemes are not defined', function() { const doc = serializeInput({}); const d = new Components(doc); - expect(typeof d.securitySchemes()).toEqual('object'); - expect(Object.keys(d.securitySchemes())).toHaveLength(0); + const items = d.securitySchemes(); + expect(items).toBeInstanceOf(SecuritySchemes); + expect(items.all()).toHaveLength(0); }); }); describe('.serverBindings()', function() { it('should return map of serverBindings', function() { - const doc = serializeInput({ serverBindings: { bidning: {} } }); + const doc = serializeInput({ serverBindings: { binding: {} } }); const d = new Components(doc); expect(typeof d.serverBindings()).toEqual('object'); expect(Object.keys(d.serverBindings())).toHaveLength(1); - expect(d.serverBindings()['bidning']).toBeInstanceOf(Bindings); + expect(d.serverBindings()['binding']).toBeInstanceOf(Bindings); }); it('should return empty map when serverBindings are not defined', function() { @@ -205,11 +238,11 @@ describe('Components model', function() { describe('.channelBindings()', function() { it('should return map of channelBindings', function() { - const doc = serializeInput({ channelBindings: { bidning: {} } }); + const doc = serializeInput({ channelBindings: { binding: {} } }); const d = new Components(doc); expect(typeof d.channelBindings()).toEqual('object'); expect(Object.keys(d.channelBindings())).toHaveLength(1); - expect(d.channelBindings()['bidning']).toBeInstanceOf(Bindings); + expect(d.channelBindings()['binding']).toBeInstanceOf(Bindings); }); it('should return empty map when channelBindings are not defined', function() { @@ -222,11 +255,11 @@ describe('Components model', function() { describe('.operationBindings()', function() { it('should return map of operationBindings', function() { - const doc = serializeInput({ operationBindings: { bidning: {} } }); + const doc = serializeInput({ operationBindings: { binding: {} } }); const d = new Components(doc); expect(typeof d.operationBindings()).toEqual('object'); expect(Object.keys(d.operationBindings())).toHaveLength(1); - expect(d.operationBindings()['bidning']).toBeInstanceOf(Bindings); + expect(d.operationBindings()['binding']).toBeInstanceOf(Bindings); }); it('should return empty map when operationBindings are not defined', function() { @@ -239,11 +272,11 @@ describe('Components model', function() { describe('.messageBindings()', function() { it('should return map of messageBindings', function() { - const doc = serializeInput({ messageBindings: { bidning: {} } }); + const doc = serializeInput({ messageBindings: { binding: {} } }); const d = new Components(doc); expect(typeof d.messageBindings()).toEqual('object'); expect(Object.keys(d.messageBindings())).toHaveLength(1); - expect(d.messageBindings()['bidning']).toBeInstanceOf(Bindings); + expect(d.messageBindings()['binding']).toBeInstanceOf(Bindings); }); it('should return empty map when messageBindings are not defined', function() { @@ -254,7 +287,18 @@ describe('Components model', function() { }); }); + describe('mixins', function() { assertExtensions(Components); }); }); + +function testCollection, T extends BaseModel>(doc: any, items: M, componentName: string, collectionModel: Constructor, itemModel: Constructor) { + expect(items).toBeInstanceOf(collectionModel); + let expectedItems: T[] = []; + Object.entries((doc[componentName] as M)).forEach(([itemName, item]) => { + expectedItems.push(new itemModel(item, {id: itemName, pointer: `/components/${componentName}/${itemName}`})); + }); + + expect(items.all()).toEqual(expectedItems); +} \ No newline at end of file From 40205d0725e0f2127a758fa9337542008838e83e Mon Sep 17 00:00:00 2001 From: Sergio Moya <1083296+smoya@users.noreply.github.com> Date: Wed, 31 Aug 2022 19:58:59 +0200 Subject: [PATCH 2/6] Update src/models/v2/channel.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Maciej Urbańczyk --- src/models/v2/channel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/v2/channel.ts b/src/models/v2/channel.ts index ba1c031c5..3c880037c 100644 --- a/src/models/v2/channel.ts +++ b/src/models/v2/channel.ts @@ -56,7 +56,7 @@ export class Channel extends BaseModel { let id = this._json[operationAction as 'publish' | 'subscribe'] && (this._json[operationAction as 'publish' | 'subscribe'] as OperationObject).operationId || this.meta().id + "_" + operationAction; this._json[operationAction as 'publish' | 'subscribe'] && operations.push( - this.createModel(Operation, this._json[operationAction as 'publish' | 'subscribe'], { id: id, action: operationAction, pointer: `${this._meta.pointer}/${operationAction}` }), + this.createModel(Operation, this._json[operationAction as 'publish' | 'subscribe'], { id, action: operationAction, pointer: `${this._meta.pointer}/${operationAction}` }), ); }); return new Operations(operations); From a97a7067d891dc0f5ea0e52c4530da9a8e210c96 Mon Sep 17 00:00:00 2001 From: Sergio Moya <1083296+smoya@users.noreply.github.com> Date: Wed, 31 Aug 2022 19:59:07 +0200 Subject: [PATCH 3/6] Update src/models/v2/components.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Maciej Urbańczyk --- src/models/v2/components.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/v2/components.ts b/src/models/v2/components.ts index e4d72586a..50e9610b2 100644 --- a/src/models/v2/components.ts +++ b/src/models/v2/components.ts @@ -115,7 +115,7 @@ export class Components extends BaseModel implements Compon } protected createCollection, T extends BaseModel>(itemsName: keyof ComponentsObject, collectionModel: Constructor, itemModel: Constructor): M { - let collectionItems: T[] = []; + const collectionItems: T[] = []; Object.entries(this._json[itemsName] || {}).forEach(([itemName, item]) => { collectionItems.push(this.createModel(itemModel, item, { id: itemName, pointer: `/components/${itemsName}/${itemName}` })) }); From c331aa47713f9a507af78701eee5b50357e2fed8 Mon Sep 17 00:00:00 2001 From: Sergio Moya <1083296+smoya@users.noreply.github.com> Date: Wed, 31 Aug 2022 19:59:12 +0200 Subject: [PATCH 4/6] Update src/models/v2/channel.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Maciej Urbańczyk --- src/models/v2/channel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/v2/channel.ts b/src/models/v2/channel.ts index 3c880037c..e99ae6feb 100644 --- a/src/models/v2/channel.ts +++ b/src/models/v2/channel.ts @@ -54,7 +54,7 @@ export class Channel extends BaseModel { - let id = this._json[operationAction as 'publish' | 'subscribe'] && (this._json[operationAction as 'publish' | 'subscribe'] as OperationObject).operationId || this.meta().id + "_" + operationAction; + const id = this._json[operationAction as 'publish' | 'subscribe'] && (this._json[operationAction as 'publish' | 'subscribe'] as OperationObject).operationId || this.meta().id + "_" + operationAction; this._json[operationAction as 'publish' | 'subscribe'] && operations.push( this.createModel(Operation, this._json[operationAction as 'publish' | 'subscribe'], { id, action: operationAction, pointer: `${this._meta.pointer}/${operationAction}` }), ); From b5dd6c5181f38b3350e3c10cc5b70f52a48d808a Mon Sep 17 00:00:00 2001 From: Sergio Moya <1083296+smoya@users.noreply.github.com> Date: Wed, 31 Aug 2022 20:21:19 +0200 Subject: [PATCH 5/6] reuse import --- src/models/v2/channel.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/models/v2/channel.ts b/src/models/v2/channel.ts index e99ae6feb..8b316f537 100644 --- a/src/models/v2/channel.ts +++ b/src/models/v2/channel.ts @@ -21,7 +21,6 @@ import type { ServersInterface } from "../servers"; import type { ServerInterface } from "../server"; import type { v2 } from "../../spec-types"; -import { OperationObject } from "spec-types/v2"; export class Channel extends BaseModel implements ChannelInterface { id(): string { @@ -54,7 +53,7 @@ export class Channel extends BaseModel { - const id = this._json[operationAction as 'publish' | 'subscribe'] && (this._json[operationAction as 'publish' | 'subscribe'] as OperationObject).operationId || this.meta().id + "_" + operationAction; + const id = this._json[operationAction as 'publish' | 'subscribe'] && (this._json[operationAction as 'publish' | 'subscribe'] as v2.OperationObject).operationId || this.meta().id + "_" + operationAction; this._json[operationAction as 'publish' | 'subscribe'] && operations.push( this.createModel(Operation, this._json[operationAction as 'publish' | 'subscribe'], { id, action: operationAction, pointer: `${this._meta.pointer}/${operationAction}` }), ); From a201a3aae7d94638fddb050ad96a27fca947c42e Mon Sep 17 00:00:00 2001 From: Sergio Moya <1083296+smoya@users.noreply.github.com> Date: Thu, 1 Sep 2022 12:46:24 +0200 Subject: [PATCH 6/6] remove address from components.channels --- src/models/v2/components.ts | 2 +- test/models/v2/components.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/models/v2/components.ts b/src/models/v2/components.ts index 50e9610b2..2ebe3c5f8 100644 --- a/src/models/v2/components.ts +++ b/src/models/v2/components.ts @@ -51,7 +51,7 @@ export class Components extends BaseModel implements Compon channels(): ChannelsInterface { return new Channels( Object.entries(this._json.channels || {}).map(([channelAddress, channel]) => - this.createModel(Channel, channel, { id: channelAddress, address: channelAddress, pointer: `/components/channels/${tilde(channelAddress)}` }) + this.createModel(Channel, channel, { id: channelAddress, pointer: `/components/channels/${tilde(channelAddress)}` }) ) ); } diff --git a/test/models/v2/components.spec.ts b/test/models/v2/components.spec.ts index 0abe25dd1..760f01130 100644 --- a/test/models/v2/components.spec.ts +++ b/test/models/v2/components.spec.ts @@ -55,7 +55,7 @@ describe('Components model', function() { const items = d.channels(); expect(items).toBeInstanceOf(Channels); expect(items.all()).toEqual([ - new Channel(doc.channels?.channel as ChannelObject, {id: "channel", address: "channel", pointer: "/components/channels/channel"} as ModelMetadata & { id: string, address: string } | undefined) + new Channel(doc.channels?.channel as ChannelObject, {id: "channel", pointer: "/components/channels/channel"} as ModelMetadata & { id: string, address: string } | undefined) ]); });