redis pt 5: fix tests
This commit is contained in:
@@ -4,8 +4,11 @@ import {
|
|||||||
UnauthorizedException,
|
UnauthorizedException,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { decode, sign } from 'jsonwebtoken';
|
import { decode, sign } from 'jsonwebtoken';
|
||||||
|
import { CacheService } from '../common/cache/cache.service';
|
||||||
|
import { CacheTagsService } from '../common/cache/cache-tags.service';
|
||||||
import { PrismaService } from '../database/prisma.service';
|
import { PrismaService } from '../database/prisma.service';
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service';
|
||||||
import { sha256 } from './auth.utils';
|
import { sha256 } from './auth.utils';
|
||||||
@@ -58,6 +61,27 @@ describe('AuthService', () => {
|
|||||||
$transaction: jest.fn(),
|
$transaction: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockEventEmitter = {
|
||||||
|
emit: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockCacheService = {
|
||||||
|
get: jest.fn().mockResolvedValue(null),
|
||||||
|
set: jest.fn().mockResolvedValue(true),
|
||||||
|
del: jest.fn().mockResolvedValue(true),
|
||||||
|
getNamespacedKey: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(
|
||||||
|
(namespace: string, key: string) => `friendolls:${namespace}:${key}`,
|
||||||
|
),
|
||||||
|
recordError: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockCacheTagsService = {
|
||||||
|
rememberKeyForTag: jest.fn().mockResolvedValue(undefined),
|
||||||
|
invalidateTag: jest.fn().mockResolvedValue(undefined),
|
||||||
|
};
|
||||||
|
|
||||||
const socialProfile: SocialAuthProfile = {
|
const socialProfile: SocialAuthProfile = {
|
||||||
provider: 'google',
|
provider: 'google',
|
||||||
providerSubject: 'google-user-123',
|
providerSubject: 'google-user-123',
|
||||||
@@ -94,6 +118,9 @@ describe('AuthService', () => {
|
|||||||
AuthService,
|
AuthService,
|
||||||
{ provide: PrismaService, useValue: mockPrismaService },
|
{ provide: PrismaService, useValue: mockPrismaService },
|
||||||
{ provide: ConfigService, useValue: mockConfigService },
|
{ provide: ConfigService, useValue: mockConfigService },
|
||||||
|
{ provide: EventEmitter2, useValue: mockEventEmitter },
|
||||||
|
{ provide: CacheService, useValue: mockCacheService },
|
||||||
|
{ provide: CacheTagsService, useValue: mockCacheTagsService },
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
@@ -135,6 +162,9 @@ describe('AuthService', () => {
|
|||||||
const localService = new AuthService(
|
const localService = new AuthService(
|
||||||
mockPrismaService as unknown as PrismaService,
|
mockPrismaService as unknown as PrismaService,
|
||||||
mockConfigService as unknown as ConfigService,
|
mockConfigService as unknown as ConfigService,
|
||||||
|
mockEventEmitter as unknown as EventEmitter2,
|
||||||
|
mockCacheService as unknown as CacheService,
|
||||||
|
mockCacheTagsService as unknown as CacheTagsService,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import { DollsService } from './dolls.service';
|
|||||||
import { PrismaService } from '../database/prisma.service';
|
import { PrismaService } from '../database/prisma.service';
|
||||||
import { NotFoundException, ForbiddenException } from '@nestjs/common';
|
import { NotFoundException, ForbiddenException } from '@nestjs/common';
|
||||||
import { Doll } from '@prisma/client';
|
import { Doll } from '@prisma/client';
|
||||||
|
import { CacheService } from '../common/cache/cache.service';
|
||||||
|
import { CacheTagsService } from '../common/cache/cache-tags.service';
|
||||||
|
import { FriendsService } from '../friends/friends.service';
|
||||||
|
|
||||||
describe('DollsService', () => {
|
describe('DollsService', () => {
|
||||||
let service: DollsService;
|
let service: DollsService;
|
||||||
@@ -31,9 +34,6 @@ describe('DollsService', () => {
|
|||||||
findFirst: jest.fn().mockResolvedValue(mockDoll),
|
findFirst: jest.fn().mockResolvedValue(mockDoll),
|
||||||
update: jest.fn().mockResolvedValue(mockDoll),
|
update: jest.fn().mockResolvedValue(mockDoll),
|
||||||
},
|
},
|
||||||
friendship: {
|
|
||||||
findMany: jest.fn().mockResolvedValue([]),
|
|
||||||
},
|
|
||||||
$transaction: jest.fn((callback) => {
|
$transaction: jest.fn((callback) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||||
return callback(mockPrismaService);
|
return callback(mockPrismaService);
|
||||||
@@ -47,6 +47,25 @@ describe('DollsService', () => {
|
|||||||
emit: jest.fn(),
|
emit: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockCacheService = {
|
||||||
|
get: jest.fn().mockResolvedValue(null),
|
||||||
|
set: jest.fn().mockResolvedValue(true),
|
||||||
|
getNamespacedKey: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(
|
||||||
|
(namespace: string, key: string) => `friendolls:${namespace}:${key}`,
|
||||||
|
),
|
||||||
|
recordError: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockCacheTagsService = {
|
||||||
|
rememberKeyForTag: jest.fn().mockResolvedValue(undefined),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockFriendsService = {
|
||||||
|
areFriends: jest.fn().mockResolvedValue(false),
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
@@ -59,6 +78,18 @@ describe('DollsService', () => {
|
|||||||
provide: EventEmitter2,
|
provide: EventEmitter2,
|
||||||
useValue: mockEventEmitter,
|
useValue: mockEventEmitter,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: CacheService,
|
||||||
|
useValue: mockCacheService,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: CacheTagsService,
|
||||||
|
useValue: mockCacheTagsService,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: FriendsService,
|
||||||
|
useValue: mockFriendsService,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
@@ -112,10 +143,7 @@ describe('DollsService', () => {
|
|||||||
const ownerId = 'friend-1';
|
const ownerId = 'friend-1';
|
||||||
const requestingUserId = 'user-1';
|
const requestingUserId = 'user-1';
|
||||||
|
|
||||||
// Mock friendship
|
(mockFriendsService.areFriends as jest.Mock).mockResolvedValueOnce(true);
|
||||||
jest
|
|
||||||
.spyOn(prismaService.friendship, 'findMany')
|
|
||||||
.mockResolvedValueOnce([{ friendId: ownerId } as any]);
|
|
||||||
|
|
||||||
await service.listByOwner(ownerId, requestingUserId);
|
await service.listByOwner(ownerId, requestingUserId);
|
||||||
|
|
||||||
@@ -134,10 +162,7 @@ describe('DollsService', () => {
|
|||||||
const ownerId = 'stranger-1';
|
const ownerId = 'stranger-1';
|
||||||
const requestingUserId = 'user-1';
|
const requestingUserId = 'user-1';
|
||||||
|
|
||||||
// Mock empty friendship (default)
|
(mockFriendsService.areFriends as jest.Mock).mockResolvedValueOnce(false);
|
||||||
jest
|
|
||||||
.spyOn(prismaService.friendship, 'findMany')
|
|
||||||
.mockResolvedValueOnce([]);
|
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
service.listByOwner(ownerId, requestingUserId),
|
service.listByOwner(ownerId, requestingUserId),
|
||||||
@@ -163,7 +188,10 @@ describe('DollsService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw NotFoundException if doll not accessible', async () => {
|
it('should throw NotFoundException if doll not accessible', async () => {
|
||||||
jest.spyOn(prismaService.doll, 'findFirst').mockResolvedValueOnce(null);
|
jest
|
||||||
|
.spyOn(prismaService.doll, 'findFirst')
|
||||||
|
.mockResolvedValueOnce({ ...mockDoll, userId: 'user-2' });
|
||||||
|
(mockFriendsService.areFriends as jest.Mock).mockResolvedValueOnce(false);
|
||||||
|
|
||||||
await expect(service.findOne('doll-1', 'user-1')).rejects.toThrow(
|
await expect(service.findOne('doll-1', 'user-1')).rejects.toThrow(
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
@@ -179,7 +207,7 @@ describe('DollsService', () => {
|
|||||||
expect(prismaService.doll.update).toHaveBeenCalled();
|
expect(prismaService.doll.update).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw ForbiddenException if not owner', async () => {
|
it('should throw NotFoundException if not owner and not a friend', async () => {
|
||||||
jest
|
jest
|
||||||
.spyOn(prismaService.doll, 'findFirst')
|
.spyOn(prismaService.doll, 'findFirst')
|
||||||
.mockResolvedValueOnce({ ...mockDoll, userId: 'user-2' });
|
.mockResolvedValueOnce({ ...mockDoll, userId: 'user-2' });
|
||||||
@@ -187,7 +215,7 @@ describe('DollsService', () => {
|
|||||||
const updateDto = { name: 'Updated Doll' };
|
const updateDto = { name: 'Updated Doll' };
|
||||||
await expect(
|
await expect(
|
||||||
service.update('doll-1', 'user-1', updateDto),
|
service.update('doll-1', 'user-1', updateDto),
|
||||||
).rejects.toThrow(ForbiddenException);
|
).rejects.toThrow(NotFoundException);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -203,13 +231,13 @@ describe('DollsService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw ForbiddenException if not owner', async () => {
|
it('should throw NotFoundException if not owner and not a friend', async () => {
|
||||||
jest
|
jest
|
||||||
.spyOn(prismaService.doll, 'findFirst')
|
.spyOn(prismaService.doll, 'findFirst')
|
||||||
.mockResolvedValueOnce({ ...mockDoll, userId: 'user-2' });
|
.mockResolvedValueOnce({ ...mockDoll, userId: 'user-2' });
|
||||||
|
|
||||||
await expect(service.remove('doll-1', 'user-1')).rejects.toThrow(
|
await expect(service.remove('doll-1', 'user-1')).rejects.toThrow(
|
||||||
ForbiddenException,
|
NotFoundException,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { Test, TestingModule } from '@nestjs/testing';
|
|||||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
import { FriendsService } from './friends.service';
|
import { FriendsService } from './friends.service';
|
||||||
import { PrismaService } from '../database/prisma.service';
|
import { PrismaService } from '../database/prisma.service';
|
||||||
|
import { CacheService } from '../common/cache/cache.service';
|
||||||
|
import { CacheTagsService } from '../common/cache/cache-tags.service';
|
||||||
import {
|
import {
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
BadRequestException,
|
BadRequestException,
|
||||||
@@ -17,6 +19,8 @@ enum FriendRequestStatus {
|
|||||||
describe('FriendsService', () => {
|
describe('FriendsService', () => {
|
||||||
let service: FriendsService;
|
let service: FriendsService;
|
||||||
let eventEmitter: EventEmitter2;
|
let eventEmitter: EventEmitter2;
|
||||||
|
let cacheService: CacheService;
|
||||||
|
let cacheTagsService: CacheTagsService;
|
||||||
|
|
||||||
const mockUser1 = {
|
const mockUser1 = {
|
||||||
id: 'user-1',
|
id: 'user-1',
|
||||||
@@ -90,6 +94,21 @@ describe('FriendsService', () => {
|
|||||||
emit: jest.fn(),
|
emit: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockCacheService = {
|
||||||
|
get: jest.fn().mockResolvedValue(null),
|
||||||
|
set: jest.fn().mockResolvedValue(true),
|
||||||
|
getNamespacedKey: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(
|
||||||
|
(namespace: string, key: string) => `friendolls:${namespace}:${key}`,
|
||||||
|
),
|
||||||
|
recordError: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockCacheTagsService = {
|
||||||
|
rememberKeyForTag: jest.fn().mockResolvedValue(undefined),
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
@@ -102,11 +121,21 @@ describe('FriendsService', () => {
|
|||||||
provide: EventEmitter2,
|
provide: EventEmitter2,
|
||||||
useValue: mockEventEmitter,
|
useValue: mockEventEmitter,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: CacheService,
|
||||||
|
useValue: mockCacheService,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: CacheTagsService,
|
||||||
|
useValue: mockCacheTagsService,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
service = module.get<FriendsService>(FriendsService);
|
service = module.get<FriendsService>(FriendsService);
|
||||||
eventEmitter = module.get<EventEmitter2>(EventEmitter2);
|
eventEmitter = module.get<EventEmitter2>(EventEmitter2);
|
||||||
|
cacheService = module.get<CacheService>(CacheService);
|
||||||
|
cacheTagsService = module.get<CacheTagsService>(CacheTagsService);
|
||||||
|
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
@@ -420,6 +449,8 @@ describe('FriendsService', () => {
|
|||||||
createdAt: 'desc',
|
createdAt: 'desc',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
expect(cacheService.set).toHaveBeenCalled();
|
||||||
|
expect(cacheTagsService.rememberKeyForTag).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -469,6 +500,12 @@ describe('FriendsService', () => {
|
|||||||
const result = await service.areFriends('user-1', 'user-2');
|
const result = await service.areFriends('user-1', 'user-2');
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
expect(cacheService.set).toHaveBeenCalledWith(
|
||||||
|
expect.any(String),
|
||||||
|
'1',
|
||||||
|
expect.any(Number),
|
||||||
|
);
|
||||||
|
expect(cacheTagsService.rememberKeyForTag).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false when users are not friends', async () => {
|
it('should return false when users are not friends', async () => {
|
||||||
@@ -477,6 +514,11 @@ describe('FriendsService', () => {
|
|||||||
const result = await service.areFriends('user-1', 'user-2');
|
const result = await service.areFriends('user-1', 'user-2');
|
||||||
|
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
|
expect(cacheService.set).toHaveBeenCalledWith(
|
||||||
|
expect.any(String),
|
||||||
|
'0',
|
||||||
|
expect.any(Number),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,9 +5,13 @@ import { NotFoundException, ForbiddenException } from '@nestjs/common';
|
|||||||
import { User } from '@prisma/client';
|
import { User } from '@prisma/client';
|
||||||
import { UpdateUserDto } from './dto/update-user.dto';
|
import { UpdateUserDto } from './dto/update-user.dto';
|
||||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
|
import { CacheService } from '../common/cache/cache.service';
|
||||||
|
import { CacheTagsService } from '../common/cache/cache-tags.service';
|
||||||
|
|
||||||
describe('UsersService', () => {
|
describe('UsersService', () => {
|
||||||
let service: UsersService;
|
let service: UsersService;
|
||||||
|
let cacheService: CacheService;
|
||||||
|
let cacheTagsService: CacheTagsService;
|
||||||
|
|
||||||
const mockUser: User & { passwordHash?: string | null } = {
|
const mockUser: User & { passwordHash?: string | null } = {
|
||||||
id: '550e8400-e29b-41d4-a716-446655440000',
|
id: '550e8400-e29b-41d4-a716-446655440000',
|
||||||
@@ -39,6 +43,21 @@ describe('UsersService', () => {
|
|||||||
emit: jest.fn(),
|
emit: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockCacheService = {
|
||||||
|
get: jest.fn().mockResolvedValue(null),
|
||||||
|
set: jest.fn().mockResolvedValue(true),
|
||||||
|
getNamespacedKey: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(
|
||||||
|
(namespace: string, key: string) => `friendolls:${namespace}:${key}`,
|
||||||
|
),
|
||||||
|
recordError: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockCacheTagsService = {
|
||||||
|
rememberKeyForTag: jest.fn().mockResolvedValue(undefined),
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
@@ -51,10 +70,20 @@ describe('UsersService', () => {
|
|||||||
provide: EventEmitter2,
|
provide: EventEmitter2,
|
||||||
useValue: mockEventEmitter,
|
useValue: mockEventEmitter,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: CacheService,
|
||||||
|
useValue: mockCacheService,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: CacheTagsService,
|
||||||
|
useValue: mockCacheTagsService,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
service = module.get<UsersService>(UsersService);
|
service = module.get<UsersService>(UsersService);
|
||||||
|
cacheService = module.get<CacheService>(CacheService);
|
||||||
|
cacheTagsService = module.get<CacheTagsService>(CacheTagsService);
|
||||||
|
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
@@ -227,6 +256,8 @@ describe('UsersService', () => {
|
|||||||
username: 'asc',
|
username: 'asc',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
expect(cacheService.set).toHaveBeenCalled();
|
||||||
|
expect(cacheTagsService.rememberKeyForTag).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should exclude specified user from results', async () => {
|
it('should exclude specified user from results', async () => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { JwtVerificationService } from '../../auth/services/jwt-verification.ser
|
|||||||
import { PrismaService } from '../../database/prisma.service';
|
import { PrismaService } from '../../database/prisma.service';
|
||||||
import { UserSocketService } from './user-socket.service';
|
import { UserSocketService } from './user-socket.service';
|
||||||
import { WsNotificationService } from './ws-notification.service';
|
import { WsNotificationService } from './ws-notification.service';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { SendInteractionDto } from '../dto/send-interaction.dto';
|
import { SendInteractionDto } from '../dto/send-interaction.dto';
|
||||||
import { WsException } from '@nestjs/websockets';
|
import { WsException } from '@nestjs/websockets';
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ describe('StateGateway', () => {
|
|||||||
let mockUserSocketService: Partial<UserSocketService>;
|
let mockUserSocketService: Partial<UserSocketService>;
|
||||||
let mockRedisClient: { publish: jest.Mock };
|
let mockRedisClient: { publish: jest.Mock };
|
||||||
let mockRedisSubscriber: { subscribe: jest.Mock; on: jest.Mock };
|
let mockRedisSubscriber: { subscribe: jest.Mock; on: jest.Mock };
|
||||||
|
let mockConfigService: { get: jest.Mock };
|
||||||
let mockWsNotificationService: {
|
let mockWsNotificationService: {
|
||||||
setIo: jest.Mock;
|
setIo: jest.Mock;
|
||||||
emitToUser: jest.Mock;
|
emitToUser: jest.Mock;
|
||||||
@@ -52,6 +54,8 @@ describe('StateGateway', () => {
|
|||||||
emitToSocket: jest.Mock;
|
emitToSocket: jest.Mock;
|
||||||
updateActiveDollCache: jest.Mock;
|
updateActiveDollCache: jest.Mock;
|
||||||
publishActiveDollUpdate: jest.Mock;
|
publishActiveDollUpdate: jest.Mock;
|
||||||
|
clearSenderNameCache: jest.Mock;
|
||||||
|
maybeTouchPresence: jest.Mock;
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@@ -92,9 +96,12 @@ describe('StateGateway', () => {
|
|||||||
mockUserSocketService = {
|
mockUserSocketService = {
|
||||||
setSocket: jest.fn().mockResolvedValue(undefined),
|
setSocket: jest.fn().mockResolvedValue(undefined),
|
||||||
removeSocket: jest.fn().mockResolvedValue(undefined),
|
removeSocket: jest.fn().mockResolvedValue(undefined),
|
||||||
|
removeSocketById: jest.fn().mockResolvedValue(undefined),
|
||||||
|
touchLastSeen: jest.fn().mockResolvedValue(undefined),
|
||||||
getSocket: jest.fn().mockResolvedValue(null),
|
getSocket: jest.fn().mockResolvedValue(null),
|
||||||
isUserOnline: jest.fn().mockResolvedValue(false),
|
isUserOnline: jest.fn().mockResolvedValue(false),
|
||||||
getFriendsSockets: jest.fn().mockResolvedValue([]),
|
getFriendsSockets: jest.fn().mockResolvedValue([]),
|
||||||
|
cleanupStalePresence: jest.fn().mockResolvedValue(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
mockRedisClient = {
|
mockRedisClient = {
|
||||||
@@ -106,6 +113,10 @@ describe('StateGateway', () => {
|
|||||||
on: jest.fn(),
|
on: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mockConfigService = {
|
||||||
|
get: jest.fn().mockReturnValue(undefined),
|
||||||
|
};
|
||||||
|
|
||||||
mockWsNotificationService = {
|
mockWsNotificationService = {
|
||||||
setIo: jest.fn(),
|
setIo: jest.fn(),
|
||||||
emitToUser: jest.fn(),
|
emitToUser: jest.fn(),
|
||||||
@@ -113,6 +124,8 @@ describe('StateGateway', () => {
|
|||||||
emitToSocket: jest.fn(),
|
emitToSocket: jest.fn(),
|
||||||
updateActiveDollCache: jest.fn(),
|
updateActiveDollCache: jest.fn(),
|
||||||
publishActiveDollUpdate: jest.fn(),
|
publishActiveDollUpdate: jest.fn(),
|
||||||
|
clearSenderNameCache: jest.fn().mockResolvedValue(undefined),
|
||||||
|
maybeTouchPresence: jest.fn().mockResolvedValue(undefined),
|
||||||
};
|
};
|
||||||
|
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
@@ -125,6 +138,7 @@ describe('StateGateway', () => {
|
|||||||
{ provide: PrismaService, useValue: mockPrismaService },
|
{ provide: PrismaService, useValue: mockPrismaService },
|
||||||
{ provide: UserSocketService, useValue: mockUserSocketService },
|
{ provide: UserSocketService, useValue: mockUserSocketService },
|
||||||
{ provide: WsNotificationService, useValue: mockWsNotificationService },
|
{ provide: WsNotificationService, useValue: mockWsNotificationService },
|
||||||
|
{ provide: ConfigService, useValue: mockConfigService },
|
||||||
{ provide: 'REDIS_CLIENT', useValue: mockRedisClient },
|
{ provide: 'REDIS_CLIENT', useValue: mockRedisClient },
|
||||||
{ provide: 'REDIS_SUBSCRIBER_CLIENT', useValue: mockRedisSubscriber },
|
{ provide: 'REDIS_SUBSCRIBER_CLIENT', useValue: mockRedisSubscriber },
|
||||||
],
|
],
|
||||||
@@ -161,9 +175,32 @@ describe('StateGateway', () => {
|
|||||||
expect(mockRedisSubscriber.subscribe).toHaveBeenCalledWith(
|
expect(mockRedisSubscriber.subscribe).toHaveBeenCalledWith(
|
||||||
'active-doll-update',
|
'active-doll-update',
|
||||||
'friend-cache-update',
|
'friend-cache-update',
|
||||||
|
'user-profile-cache-invalidate',
|
||||||
expect.any(Function),
|
expect.any(Function),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should route user profile cache invalidation messages', async () => {
|
||||||
|
gateway.afterInit();
|
||||||
|
|
||||||
|
const onCalls = (mockRedisSubscriber.on as jest.Mock).mock.calls;
|
||||||
|
const messageHandler = onCalls.find(
|
||||||
|
(call) => call[0] === 'message',
|
||||||
|
)?.[1] as ((channel: string, message: string) => void) | undefined;
|
||||||
|
|
||||||
|
expect(messageHandler).toBeDefined();
|
||||||
|
|
||||||
|
messageHandler?.(
|
||||||
|
'user-profile-cache-invalidate',
|
||||||
|
JSON.stringify({ userId: 'user-1' }),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.resolve();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
mockWsNotificationService.clearSenderNameCache,
|
||||||
|
).toHaveBeenCalledWith('user-1');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handleConnection', () => {
|
describe('handleConnection', () => {
|
||||||
@@ -260,6 +297,9 @@ describe('StateGateway', () => {
|
|||||||
'user-id',
|
'user-id',
|
||||||
'client1',
|
'client1',
|
||||||
);
|
);
|
||||||
|
expect(mockUserSocketService.touchLastSeen).toHaveBeenCalledWith(
|
||||||
|
'user-id',
|
||||||
|
);
|
||||||
|
|
||||||
// 2. Fetch State (DB)
|
// 2. Fetch State (DB)
|
||||||
expect(mockPrismaService.user!.findUnique).toHaveBeenCalledWith({
|
expect(mockPrismaService.user!.findUnique).toHaveBeenCalledWith({
|
||||||
@@ -359,6 +399,13 @@ describe('StateGateway', () => {
|
|||||||
expect(mockUserSocketService.getSocket).toHaveBeenCalledWith('user-id');
|
expect(mockUserSocketService.getSocket).toHaveBeenCalledWith('user-id');
|
||||||
expect(mockUserSocketService.removeSocket).toHaveBeenCalledWith(
|
expect(mockUserSocketService.removeSocket).toHaveBeenCalledWith(
|
||||||
'user-id',
|
'user-id',
|
||||||
|
'client1',
|
||||||
|
);
|
||||||
|
expect(mockUserSocketService.touchLastSeen).toHaveBeenCalledWith(
|
||||||
|
'user-id',
|
||||||
|
);
|
||||||
|
expect(mockUserSocketService.removeSocketById).toHaveBeenCalledWith(
|
||||||
|
'client1',
|
||||||
);
|
);
|
||||||
expect(mockWsNotificationService.emitToSocket).toHaveBeenCalledWith(
|
expect(mockWsNotificationService.emitToSocket).toHaveBeenCalledWith(
|
||||||
'friend-socket-id',
|
'friend-socket-id',
|
||||||
|
|||||||
Reference in New Issue
Block a user