diff --git a/src/BaseFirestoreRepository.spec.ts b/src/BaseFirestoreRepository.spec.ts index f6bfca0..412df69 100644 --- a/src/BaseFirestoreRepository.spec.ts +++ b/src/BaseFirestoreRepository.spec.ts @@ -22,7 +22,7 @@ describe('BaseFirestoreRepository', () => { let firestore: Firestore; beforeEach(() => { - const fixture = Object.assign({}, getFixture()); + const fixture = { ...getFixture() }; const firebase = new MockFirebase(fixture, { isNaiveSnapshotListenerEnabled: false, }); @@ -84,63 +84,61 @@ describe('BaseFirestoreRepository', () => { it.todo('must throw if the limit is less than 0'); }); - describe('ordering', () => { - describe('orderByAscending', () => { - it('must order repository objects', async () => { - const bands = await bandRepository.orderByAscending('formationYear').find(); - expect(bands[0].id).toEqual('the-speckled-band'); - }); + describe('orderByAscending', () => { + it('must order repository objects', async () => { + const bands = await bandRepository.orderByAscending('formationYear').find(); + expect(bands[0].id).toEqual('the-speckled-band'); + }); - it('must order the objects in a subcollection', async () => { - const pt = await bandRepository.findById('porcupine-tree'); - const albumsSubColl = pt?.albums; - const discographyNewestFirst = await albumsSubColl?.orderByAscending('releaseDate').find(); - if (discographyNewestFirst) { - expect(discographyNewestFirst[0].id).toEqual('lightbulb-sun'); - } - }); + it('must order the objects in a subcollection', async () => { + const pt = await bandRepository.findById('porcupine-tree'); + const albumsSubColl = pt?.albums; + const discographyNewestFirst = await albumsSubColl?.orderByAscending('releaseDate').find(); + if (discographyNewestFirst) { + expect(discographyNewestFirst[0].id).toEqual('lightbulb-sun'); + } + }); - it('must be chainable with where* filters', async () => { - const pt = await bandRepository.findById('porcupine-tree'); - const albumsSubColl = pt?.albums; - const discographyNewestFirst = await albumsSubColl - ?.whereGreaterOrEqualThan('releaseDate', new Date('2001-01-01')) - .orderByAscending('releaseDate') - .find(); - if (discographyNewestFirst) { - expect(discographyNewestFirst[0].id).toEqual('in-absentia'); - } - }); + it('must be chainable with where* filters', async () => { + const pt = await bandRepository.findById('porcupine-tree'); + const albumsSubColl = pt?.albums; + const discographyNewestFirst = await albumsSubColl + ?.whereGreaterOrEqualThan('releaseDate', new Date('2001-01-01')) + .orderByAscending('releaseDate') + .find(); + if (discographyNewestFirst) { + expect(discographyNewestFirst[0].id).toEqual('in-absentia'); + } + }); - it('must be chainable with limit', async () => { - const bands = await bandRepository.orderByAscending('formationYear').limit(3).find(); - const lastBand = bands[bands.length - 1]; - expect(lastBand.id).toEqual('red-hot-chili-peppers'); - }); + it('must be chainable with limit', async () => { + const bands = await bandRepository.orderByAscending('formationYear').limit(3).find(); + const lastBand = bands[bands.length - 1]; + expect(lastBand.id).toEqual('red-hot-chili-peppers'); + }); - it('must throw an Error if an orderBy* function is called more than once in the same expression', async () => { - const pt = await bandRepository.findById('porcupine-tree'); - const albumsSubColl = pt?.albums; - expect(() => { - albumsSubColl?.orderByAscending('releaseDate').orderByDescending('releaseDate'); - }).toThrow(); - }); + it('must throw an Error if an orderBy* function is called more than once in the same expression', async () => { + const pt = await bandRepository.findById('porcupine-tree'); + const albumsSubColl = pt?.albums; + expect(() => { + albumsSubColl?.orderByAscending('releaseDate').orderByDescending('releaseDate'); + }).toThrow(); + }); - it('must throw an Error if an orderBy* function is called more than once in the same expression ascending', async () => { - const pt = await bandRepository.findById('porcupine-tree'); - const albumsSubColl = pt?.albums; - expect(() => { - albumsSubColl?.orderByAscending('releaseDate').orderByAscending('releaseDate'); - }).toThrow(); - }); + it('must throw an Error if an orderBy* function is called more than once in the same expression ascending', async () => { + const pt = await bandRepository.findById('porcupine-tree'); + const albumsSubColl = pt?.albums; + expect(() => { + albumsSubColl?.orderByAscending('releaseDate').orderByAscending('releaseDate'); + }).toThrow(); + }); - it('must succeed when orderBy* function is called more than once in the same expression with different fields', async () => { - const pt = await bandRepository.findById('porcupine-tree'); - const albumsSubColl = pt?.albums; - expect(() => { - albumsSubColl?.orderByAscending('releaseDate').orderByDescending('name'); - }).not.toThrow(); - }); + it('must succeed when orderBy* function is called more than once in the same expression with different fields', async () => { + const pt = await bandRepository.findById('porcupine-tree'); + const albumsSubColl = pt?.albums; + expect(() => { + albumsSubColl?.orderByAscending('releaseDate').orderByDescending('name'); + }).not.toThrow(); }); }); diff --git a/src/MetadataStorage.spec.ts b/src/MetadataStorage.spec.ts index 536ece8..8c5fa4d 100644 --- a/src/MetadataStorage.spec.ts +++ b/src/MetadataStorage.spec.ts @@ -8,45 +8,154 @@ import { BaseFirestoreRepository } from './BaseFirestoreRepository'; import { IRepository, Constructor } from './types'; import { CollectionPathNotFoundError, InvalidRepositoryIndexError } from './Errors'; -describe('MetadataStorage', () => { +class Entity { + id: string; +} + +class SubEntity { + id: string; +} + +class SubSubEntity { + public id: string; +} + +const col: EnforcedCollectionMetadata = { + entityConstructor: Entity, + name: 'entity', + parentProps: null, +}; + +const subCol: EnforcedCollectionMetadata = { + entityConstructor: SubEntity, + name: 'subEntity', + parentProps: { + parentEntityConstructor: Entity, + parentPropertyKey: 'subEntities', + parentCollectionName: 'entity', + }, +}; + +const subSubCol: EnforcedCollectionMetadata = { + entityConstructor: SubSubEntity, + name: 'subSubEntity', + parentProps: { + parentEntityConstructor: SubEntity, + parentPropertyKey: 'subSubEntities', + parentCollectionName: 'subEntity', + }, +}; + +describe('MetadataStorage: Private Methods', () => { + describe('isSubCollectionMetadata', () => { + it('should return true for correctly configured subcollection metadata', () => { + class TestClass { + id: string; + value: string; + constructor(value: string) { + this.value = value; + } + } + class TestClass2 { + id: string; + value: string; + constructor(value: string) { + this.value = value; + } + } + + const classInstance = new MetadataStorage(); + const subCollectioMetadata = { + entityConstructor: TestClass, + name: 'test', + parentProps: { + parentCollectionName: 'test2', + parentEntityConstructor: TestClass2, + parentPropertyKey: 'test', + }, + } as EnforcedCollectionMetadata; + + const result = (classInstance as any)['isSubCollectionMetadata'](subCollectioMetadata); + expect(result).toEqual(true); + }); + + it('should return false for collection metadata or any incorrect type', () => { + class TestClass { + id: string; + value: string; + constructor(value: string) { + this.value = value; + } + } + + const classInstance = new MetadataStorage(); + const subCollectioMetadata = { + entityConstructor: TestClass, + name: 'test', + parentProps: null, + } as EnforcedCollectionMetadata; + + const result = (classInstance as any)['isSubCollectionMetadata'](subCollectioMetadata); + expect(result).toEqual(false); + const result2 = (classInstance as any)['isSubCollectionMetadata']({}); + expect(result2).toEqual(false); + }); + }); + + describe('isSameCollection', () => { + it('should return true when inputs are equivalent values', () => { + class TestClass { + id: string; + value: string; + constructor(value: string) { + this.value = value; + } + } + + const classInstance = new MetadataStorage(); + const subCollectioMetadata = { + entityConstructor: TestClass, + name: 'test', + parentProps: null, + } as EnforcedCollectionMetadata; + const sameCollectionMetadata = subCollectioMetadata; + + const result = (classInstance as any)['isSameCollection']( + subCollectioMetadata, + sameCollectionMetadata + ); + expect(result).toEqual(true); + }); + + it('should return false for the incorrect input type', () => { + class TestClass { + id: string; + value: string; + constructor(value: string) { + this.value = value; + } + } + + const classInstance = new MetadataStorage(); + const subCollectioMetadata = { + entityConstructor: TestClass, + name: 'test', + parentProps: null, + } as EnforcedCollectionMetadata; + const sameCollectionMetadata = { ...subCollectioMetadata }; + sameCollectionMetadata.name = 'test2'; + + const result = (classInstance as any)['isSameCollection']( + subCollectioMetadata, + sameCollectionMetadata + ); + expect(result).toEqual(false); + }); + }); +}); + +describe('MetadataStorage: Public Methods', () => { let metadataStorage: MetadataStorage; - class Entity { - id: string; - } - - class SubEntity { - id: string; - } - - class SubSubEntity { - public id: string; - } - - const col: EnforcedCollectionMetadata = { - entityConstructor: Entity, - name: 'entity', - parentProps: null, - }; - - const subCol: EnforcedCollectionMetadata = { - entityConstructor: SubEntity, - name: 'subEntity', - parentProps: { - parentEntityConstructor: Entity, - parentPropertyKey: 'subEntities', - parentCollectionName: 'entity', - }, - }; - - const subSubCol: EnforcedCollectionMetadata = { - entityConstructor: SubSubEntity, - name: 'subSubEntity', - parentProps: { - parentEntityConstructor: SubEntity, - parentPropertyKey: 'subSubEntities', - parentCollectionName: 'subEntity', - }, - }; beforeEach(() => { metadataStorage = new MetadataStorage(); @@ -272,112 +381,4 @@ describe('MetadataStorage', () => { expect(() => validateRepositoryIndex(['string', 'string'])).not.toThrow(); }); }); - - describe('private methods', () => { - describe('isSubCollectionMetadata', () => { - it('should return true for correctly configured subcollection metadata', () => { - class TestClass { - id: string; - value: string; - constructor(value: string) { - this.value = value; - } - } - class TestClass2 { - id: string; - value: string; - constructor(value: string) { - this.value = value; - } - } - - const classInstance = new MetadataStorage(); - const subCollectioMetadata = { - entityConstructor: TestClass, - name: 'test', - parentProps: { - parentCollectionName: 'test2', - parentEntityConstructor: TestClass2, - parentPropertyKey: 'test', - }, - } as EnforcedCollectionMetadata; - - const result = (classInstance as any)['isSubCollectionMetadata'](subCollectioMetadata); - expect(result).toEqual(true); - }); - - it('should return false for collection metadata or any incorrect type', () => { - class TestClass { - id: string; - value: string; - constructor(value: string) { - this.value = value; - } - } - - const classInstance = new MetadataStorage(); - const subCollectioMetadata = { - entityConstructor: TestClass, - name: 'test', - parentProps: null, - } as EnforcedCollectionMetadata; - - const result = (classInstance as any)['isSubCollectionMetadata'](subCollectioMetadata); - expect(result).toEqual(false); - const result2 = (classInstance as any)['isSubCollectionMetadata']({}); - expect(result2).toEqual(false); - }); - }); - - describe('isSameCollection', () => { - it('should return true when inputs are equivalent values', () => { - class TestClass { - id: string; - value: string; - constructor(value: string) { - this.value = value; - } - } - - const classInstance = new MetadataStorage(); - const subCollectioMetadata = { - entityConstructor: TestClass, - name: 'test', - parentProps: null, - } as EnforcedCollectionMetadata; - const sameCollectionMetadata = subCollectioMetadata; - - const result = (classInstance as any)['isSameCollection']( - subCollectioMetadata, - sameCollectionMetadata - ); - expect(result).toEqual(true); - }); - - it('should return false for the incorrect input type', () => { - class TestClass { - id: string; - value: string; - constructor(value: string) { - this.value = value; - } - } - - const classInstance = new MetadataStorage(); - const subCollectioMetadata = { - entityConstructor: TestClass, - name: 'test', - parentProps: null, - } as EnforcedCollectionMetadata; - const sameCollectionMetadata = { ...subCollectioMetadata }; - sameCollectionMetadata.name = 'test2'; - - const result = (classInstance as any)['isSameCollection']( - subCollectioMetadata, - sameCollectionMetadata - ); - expect(result).toEqual(false); - }); - }); - }); }); diff --git a/src/MetadataStorage.ts b/src/MetadataStorage.ts index 3f31024..761c066 100644 --- a/src/MetadataStorage.ts +++ b/src/MetadataStorage.ts @@ -168,7 +168,7 @@ export class MetadataStorage { this.isSameCollection(registeredCollection, col) ); - if (existing && this.config.throwOnDuplicatedCollection == true) { + if (existing && this.config.throwOnDuplicatedCollection) { if (colIsSubCollection) { throw new DuplicateSubCollectionError( existing.entityConstructor.name, @@ -222,7 +222,7 @@ export class MetadataStorage { }; public getRepository = (entityConstructor: IEntityConstructor, collectionName?: string) => { - const repo_index = [entityConstructor.name, collectionName ? collectionName : null]; + const repo_index = [entityConstructor.name, collectionName || null]; validateRepositoryIndex(repo_index); return this.repositories.get(JSON.stringify(repo_index)) || null; }; diff --git a/src/helpers.spec.ts b/src/helpers.spec.ts index a538ab8..af3b2af 100644 --- a/src/helpers.spec.ts +++ b/src/helpers.spec.ts @@ -29,7 +29,7 @@ describe('Error state', () => { it('runTransaction: should throw error if firebase is not initialized', async () => { expect( runTransaction(async () => { - const thing = 'value'; + console.log('Useless operation so the function is not empty'); }) ).rejects.toThrow(NoFirestoreError); }); diff --git a/src/types.ts b/src/types.ts index c7ea7e6..0b54534 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,9 @@ -import { OrderByDirection, DocumentReference, CollectionReference } from '@google-cloud/firestore'; -import { Query } from '@google-cloud/firestore'; +import { + OrderByDirection, + DocumentReference, + CollectionReference, + Query, +} from '@google-cloud/firestore'; export type PartialBy = Omit & Partial>; export type PartialWithRequiredBy = Pick & Partial>; @@ -135,8 +139,8 @@ export interface IEntity { id: string; } -export type Constructor = { new (...args: any[]): T }; -export type EntityConstructorOrPathConstructor = { new (...args: any[]): T }; +export type Constructor = new (...args: any[]) => T; +export type EntityConstructorOrPathConstructor = new (...args: any[]) => T; export type IEntityConstructor = Constructor; export type IEntityRepositoryConstructor = Constructor>; export type EntityConstructorOrPath = Constructor | string; diff --git a/src/utils.spec.ts b/src/utils.spec.ts index 3d6968b..1b4f04f 100644 --- a/src/utils.spec.ts +++ b/src/utils.spec.ts @@ -4,42 +4,40 @@ import { extractAllGetters, serializeEntity } from './utils'; describe('Utils', () => { describe('extractAllGetter', () => { - describe('Class', () => { - it('should return only getters not data property', () => { - class ClassTest { - public a = 'a'; - private _c; - - public get b() { - return 'b'; - } + it('should return only getters, not data properties of ClassTest', () => { + class ClassTest { + public a = 'a'; + private _c; + + public get b() { + return 'b'; } + } - const b = new ClassTest(); + const b = new ClassTest(); - const extracted = extractAllGetters(b as unknown as Record); - expect(extracted).toEqual({ b: 'b' }); - }); + const extracted = extractAllGetters(b as unknown as Record); + expect(extracted).toEqual({ b: 'b' }); + }); - it('should return only getters not method', () => { - class ClassTest { - public get b() { - return 'b'; - } + it('should return only getters, not methods of ClassTest', () => { + class ClassTest { + public get b() { + return 'b'; + } - public a() { - return 'a method'; - } + public a() { + return 'a method'; } + } - const b = new ClassTest(); + const b = new ClassTest(); - const extracted = extractAllGetters(b as unknown as Record); - expect(extracted).toEqual({ b: 'b' }); - }); + const extracted = extractAllGetters(b as unknown as Record); + expect(extracted).toEqual({ b: 'b' }); }); - it('should return only getters which return undefined', () => { + it('should return only getters which do not return undefined', () => { class ClassTest { public a = 'a';