71 lines
2.6 KiB
TypeScript
71 lines
2.6 KiB
TypeScript
import { ConfigService } from '@nestjs/config';
|
|
import { JwtService } from '@nestjs/jwt';
|
|
import { Socket } from 'socket.io';
|
|
import { NotificationsGateway } from './notifications.gateway';
|
|
import { JwtStrategy } from '../auth/jwt.strategy';
|
|
import { AuthService } from '../auth/auth.service';
|
|
import { NotificationService } from '../services/notification.service';
|
|
|
|
describe('notification socket sessions', () => {
|
|
const jwt = new JwtService({ secret: 'test-only-socket-secret' });
|
|
const validateUser = jest.fn();
|
|
const notifications = {
|
|
getUnreadCount: jest.fn(async () => 0),
|
|
getRecentNotifications: jest.fn(async () => []),
|
|
markAllAsRead: jest.fn(),
|
|
};
|
|
let gateway: NotificationsGateway;
|
|
const socket = (token: string) =>
|
|
({
|
|
id: 'socket-1',
|
|
data: {},
|
|
handshake: { headers: {}, query: {}, auth: { token } },
|
|
join: jest.fn(),
|
|
emit: jest.fn(),
|
|
disconnect: jest.fn(),
|
|
}) as unknown as Socket;
|
|
const token = (type = 'access', expiresIn = 300) =>
|
|
jwt.sign({ sub: 'user-1', type }, { expiresIn });
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
validateUser.mockResolvedValue({ id: 'user-1', organizationId: 'org-1' });
|
|
const strategy = new JwtStrategy(new ConfigService({ JWT_SECRET: 'test-only-socket-secret' }), {
|
|
validateUser,
|
|
} as unknown as AuthService);
|
|
gateway = new NotificationsGateway(
|
|
jwt,
|
|
notifications as unknown as NotificationService,
|
|
strategy
|
|
);
|
|
});
|
|
|
|
it.each(['refresh', 'unknown'])('rejects %s tokens before any data is sent', async type => {
|
|
const client = socket(token(type));
|
|
await gateway.handleConnection(client);
|
|
expect(client.disconnect).toHaveBeenCalled();
|
|
expect(client.emit).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('rejects expired and disabled sessions', async () => {
|
|
const expired = socket(token('access', -1));
|
|
await gateway.handleConnection(expired);
|
|
expect(expired.emit).not.toHaveBeenCalled();
|
|
validateUser.mockResolvedValue(null);
|
|
const disabled = socket(token());
|
|
await gateway.handleConnection(disabled);
|
|
expect(disabled.emit).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('rechecks the account on messages after a valid connection', async () => {
|
|
const client = socket(token());
|
|
await gateway.handleConnection(client);
|
|
expect(client.emit).toHaveBeenCalledWith('unread_count', { count: 0 });
|
|
validateUser.mockResolvedValue(null);
|
|
const result = await gateway.handleMarkAllAsRead(client);
|
|
expect(result.success).toBe(false);
|
|
expect(notifications.markAllAsRead).not.toHaveBeenCalled();
|
|
expect(client.disconnect).toHaveBeenCalled();
|
|
});
|
|
});
|