diff --git a/src/players/models/player.ts b/src/players/models/player.ts index 60dcbe6cd..0079346da 100644 --- a/src/players/models/player.ts +++ b/src/players/models/player.ts @@ -38,6 +38,7 @@ export class Player extends MongooseDocument { @Prop({ index: true }) etf2lProfileId?: number; + @Exclude({ toPlainOnly: true }) @ExposeObjectId() @Prop({ ref: 'Game' }) activeGame?: Types.ObjectId; diff --git a/src/profile/services/profile.service.spec.ts b/src/profile/services/profile.service.spec.ts index a08ea2d2b..3a5517e75 100644 --- a/src/profile/services/profile.service.spec.ts +++ b/src/profile/services/profile.service.spec.ts @@ -5,6 +5,7 @@ import { OnlinePlayersService } from '@/players/services/online-players.service' import { WebsocketEvent } from '@/websocket-event'; import { Test, TestingModule } from '@nestjs/testing'; import { Types } from 'mongoose'; +import { Subject } from 'rxjs'; import { ProfileService } from './profile.service'; jest.mock('@/players/services/online-players.service'); @@ -15,6 +16,15 @@ describe('ProfileService', () => { let onlinePlayersService: jest.Mocked; let linkedProfilesService: jest.Mocked; let events: Events; + let socketEvents: Subject; + let socket; + + beforeEach(() => { + socketEvents = new Subject(); + socket = { + emit: (eventName, data) => socketEvents.next({ eventName, data }), + }; + }); beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ @@ -28,58 +38,54 @@ describe('ProfileService', () => { onlinePlayersService = module.get(OnlinePlayersService); linkedProfilesService = module.get(LinkedProfilesService); + + onlinePlayersService.getSocketsForPlayer.mockReturnValue([socket as any]); + events = module.get(Events); service = module.get(ProfileService); service.onModuleInit(); }); + afterEach(() => { + socketEvents.complete(); + }); + it('should be defined', () => { expect(service).toBeDefined(); }); - it('should update profile on linkedProfilesChanged event', async () => - new Promise((resolve) => { - const socket = { - emit: jest.fn().mockImplementation((eventName, data) => { - expect(eventName).toEqual(WebsocketEvent.profileUpdate); - expect(data).toMatchObject({ - linkedProfiles: [], - }); - resolve(); - }), - }; - - onlinePlayersService.getSocketsForPlayer.mockReturnValue([socket as any]); - linkedProfilesService.getLinkedProfiles.mockResolvedValue([]); - events.linkedProfilesChanged.next({ playerId: 'FAKE_PLAYER_ID' }); - })); + it('should update profile on linkedProfilesChanged event', () => { + socketEvents.subscribe(({ eventName, data }) => { + expect(eventName).toEqual(WebsocketEvent.profileUpdate); + expect(data).toMatchObject({ + linkedProfiles: [], + }); + }); - it('should update profile when active game is updated', async () => - new Promise((resolve) => { - const socket = { - emit: jest.fn().mockImplementation((eventName, data) => { - expect(eventName).toEqual(WebsocketEvent.profileUpdate); - expect(data).toMatchObject({ - activeGameId: null, - }); - resolve(); - }), - }; + linkedProfilesService.getLinkedProfiles.mockResolvedValue([]); + events.linkedProfilesChanged.next({ playerId: 'FAKE_PLAYER_ID' }); + }); - onlinePlayersService.getSocketsForPlayer.mockReturnValue([socket as any]); + it('should update profile when active game is updated', () => { + socketEvents.subscribe(({ eventName, data }) => { + expect(eventName).toEqual(WebsocketEvent.profileUpdate); + expect(data).toMatchObject({ + activeGameId: null, + }); + }); - const oldPlayer = new Player(); - oldPlayer.id = 'FAKE_PLAYER_ID'; - oldPlayer.name = 'FAKE_PLAYER_NAME'; - oldPlayer.activeGame = new Types.ObjectId(); + const oldPlayer = new Player(); + oldPlayer.id = 'FAKE_PLAYER_ID'; + oldPlayer.name = 'FAKE_PLAYER_NAME'; + oldPlayer.activeGame = new Types.ObjectId(); - const newPlayer = new Player(); - newPlayer.id = 'FAKE_PLAYER_ID'; - newPlayer.name = 'FAKE_PLAYER_NAME'; + const newPlayer = new Player(); + newPlayer.id = 'FAKE_PLAYER_ID'; + newPlayer.name = 'FAKE_PLAYER_NAME'; - events.playerUpdates.next({ - oldPlayer, - newPlayer, - }); - })); + events.playerUpdates.next({ + oldPlayer, + newPlayer, + }); + }); }); diff --git a/src/shared/decorators/expose-object-id.ts b/src/shared/decorators/expose-object-id.ts index 7ec29b0a0..4d048b250 100644 --- a/src/shared/decorators/expose-object-id.ts +++ b/src/shared/decorators/expose-object-id.ts @@ -1,32 +1,16 @@ import { Transform, TransformationType } from 'class-transformer'; -import { merge } from 'lodash'; -interface ExposeObjectIdOptions { - toClass?: boolean; - toPlain?: boolean; -} +export const ExposeObjectId = () => (target: any, propertyKey: string) => { + Transform(({ type, obj }) => { + switch (type) { + case TransformationType.PLAIN_TO_CLASS: + return obj[propertyKey]; -export const ExposeObjectId = - (options?: ExposeObjectIdOptions) => (target: any, propertyKey: string) => { - const mergedOptions = merge({ toClass: true, toPlain: true }, options); - Transform(({ type, obj }) => { - switch (type) { - case TransformationType.PLAIN_TO_CLASS: - if (mergedOptions.toClass) { - return obj[propertyKey]; - } else { - return undefined; - } + case TransformationType.CLASS_TO_PLAIN: + return obj[propertyKey].toString(); - case TransformationType.CLASS_TO_PLAIN: - if (mergedOptions.toPlain) { - return obj[propertyKey].toString(); - } else { - return undefined; - } - - case TransformationType.CLASS_TO_CLASS: - return obj[propertyKey]; - } - })(target, propertyKey); - }; + case TransformationType.CLASS_TO_CLASS: + return obj[propertyKey]; + } + })(target, propertyKey); +}; diff --git a/src/utils/mongoose-document.ts b/src/utils/mongoose-document.ts index 64eaa405c..3ad484278 100644 --- a/src/utils/mongoose-document.ts +++ b/src/utils/mongoose-document.ts @@ -6,6 +6,7 @@ export abstract class MongooseDocument { @Exclude({ toPlainOnly: true }) __v?: number; - @ExposeObjectId({ toPlain: false }) + @Exclude({ toPlainOnly: true }) + @ExposeObjectId() _id?: Types.ObjectId; }