diff --git a/.changeset/fix-collection-native-array-methods.md b/.changeset/fix-collection-native-array-methods.md new file mode 100644 index 000000000..fbefd2201 --- /dev/null +++ b/.changeset/fix-collection-native-array-methods.md @@ -0,0 +1,5 @@ +--- +"@asyncapi/parser": patch +--- + +Fix native array methods on parser collections. diff --git a/packages/parser/src/models/collection.ts b/packages/parser/src/models/collection.ts index e7a290cfe..7ad6cc7c7 100644 --- a/packages/parser/src/models/collection.ts +++ b/packages/parser/src/models/collection.ts @@ -8,6 +8,10 @@ export interface CollectionMetadata { } export abstract class Collection = {}> extends Array { + static get [Symbol.species](): ArrayConstructor { + return Array; + } + constructor( protected readonly collections: T[], protected readonly _meta: CollectionMetadata & M = {} as CollectionMetadata & M, diff --git a/packages/parser/test/models/collection.spec.ts b/packages/parser/test/models/collection.spec.ts index d2fe33400..0067575fe 100644 --- a/packages/parser/test/models/collection.spec.ts +++ b/packages/parser/test/models/collection.spec.ts @@ -96,4 +96,46 @@ describe('Collection model', function() { expect(d.filterBy(filter)).toEqual([]); }); }); + + describe('native array methods', function() { + const createCollection = () => { + const item1 = new ItemModel({ name: 'name1' }); + const item2 = new ItemModel({ name: 'name2' }); + return { collection: new Model([item1, item2]), item1, item2 }; + }; + + it('should map collection items into a plain array', function() { + const { collection } = createCollection(); + + const names = collection.map(item => item.name()); + + expect(names).toEqual(['name1', 'name2']); + expect(names).toBeInstanceOf(Array); + expect(names).not.toBeInstanceOf(Model); + }); + + it('should return plain arrays from filter and slice', function() { + const { collection, item1, item2 } = createCollection(); + + const filtered = collection.filter(item => item.name() === 'name2'); + const sliced = collection.slice(0, 1); + + expect(filtered).toEqual([item2]); + expect(sliced).toEqual([item1]); + expect(filtered).not.toBeInstanceOf(Model); + expect(sliced).not.toBeInstanceOf(Model); + }); + + it('should leave the source collection unchanged', function() { + const { collection, item1, item2 } = createCollection(); + + collection.map(item => item.name()); + collection.filter(item => item.name() === 'name1'); + collection.slice(1); + + expect(collection).toBeInstanceOf(Model); + expect(collection.all()).toEqual([item1, item2]); + expect(collection.meta()).toEqual({}); + }); + }); });