feat: add AccountsModule with list and QR endpoints

Implements GET /accounts (list all accounts) and GET /accounts/:id/qr
(returns QR code as base64 data URL) using the qrcode package.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-29 11:15:42 +05:30
parent 02dad1347c
commit 1dba77959d
8 changed files with 268 additions and 0 deletions
@@ -0,0 +1,66 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AccountsService } from './accounts.service';
import { PrismaService } from '../../prisma/prisma.service';
import * as QRCode from 'qrcode';
jest.mock('qrcode', () => ({
toDataURL: jest.fn().mockResolvedValue('data:image/png;base64,fakedata'),
}));
const mockAccounts = [
{ id: 'acc_1', platform: 'whatsapp', jid: '111@s.whatsapp.net', displayName: 'Test Account', status: 'ACTIVE' },
];
const mockPrisma = {
account: {
findMany: jest.fn().mockResolvedValue(mockAccounts),
findUnique: jest.fn(),
},
};
describe('AccountsService', () => {
let service: AccountsService;
beforeEach(async () => {
jest.clearAllMocks();
const module: TestingModule = await Test.createTestingModule({
providers: [
AccountsService,
{ provide: PrismaService, useValue: mockPrisma },
],
}).compile();
service = module.get<AccountsService>(AccountsService);
});
describe('list()', () => {
it('returns accounts from Prisma without qrCode field', async () => {
const result = await service.list();
expect(result).toEqual(mockAccounts);
expect(mockPrisma.account.findMany).toHaveBeenCalledWith(
expect.objectContaining({ select: expect.not.objectContaining({ qrCode: true }) }),
);
});
});
describe('getQr()', () => {
it('returns null qrDataUrl when account has no qrCode', async () => {
mockPrisma.account.findUnique.mockResolvedValue({ status: 'ACTIVE', qrCode: null });
const result = await service.getQr('acc_1');
expect(result).toEqual({ status: 'ACTIVE', qrDataUrl: null });
expect(QRCode.toDataURL).not.toHaveBeenCalled();
});
it('converts qrCode string to data URL when qrCode is present', async () => {
mockPrisma.account.findUnique.mockResolvedValue({ status: 'DISCONNECTED', qrCode: 'raw-qr-string' });
const result = await service.getQr('acc_1');
expect(QRCode.toDataURL).toHaveBeenCalledWith('raw-qr-string');
expect(result).toEqual({ status: 'DISCONNECTED', qrDataUrl: 'data:image/png;base64,fakedata' });
});
it('returns not_found status when account does not exist', async () => {
mockPrisma.account.findUnique.mockResolvedValue(null);
const result = await service.getQr('nonexistent');
expect(result).toEqual({ status: 'not_found', qrDataUrl: null });
});
});
});