You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			84 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			84 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
| import { describe, it, beforeEach, afterEach, expect } from 'bun:test';
 | |
| import Database from 'bun:sqlite';
 | |
| import { initializeDatabase } from '../../../src/db';
 | |
| import { GroupSyncService } from '../../../src/services/group-sync';
 | |
| import { AllowedGroups } from '../../../src/services/allowed-groups';
 | |
| 
 | |
| const envBackup = { ...process.env } as NodeJS.ProcessEnv;
 | |
| 
 | |
| describe('GroupSyncService - onboarding A3', () => {
 | |
|   let memdb: Database;
 | |
| 
 | |
|   beforeEach(() => {
 | |
|     process.env = {
 | |
|       ...envBackup,
 | |
|       NODE_ENV: 'test',
 | |
|       ONBOARDING_ENABLE_IN_TEST: 'true',
 | |
|       ONBOARDING_PROMPTS_ENABLED: 'true',
 | |
|       ONBOARDING_GRACE_SECONDS: '0',
 | |
|       ONBOARDING_COOLDOWN_DAYS: '7',
 | |
|       ONBOARDING_COVERAGE_THRESHOLD: '1',
 | |
|       CHATBOT_PHONE_NUMBER: '555111222'
 | |
|     };
 | |
|     memdb = new Database(':memory:');
 | |
|     initializeDatabase(memdb);
 | |
|     (GroupSyncService as any).dbInstance = memdb;
 | |
|     (AllowedGroups as any).dbInstance = memdb;
 | |
| 
 | |
|     // Sembrar grupo activo
 | |
|     memdb.prepare(`INSERT INTO groups (id, community_id, name, active, last_verified) VALUES (?,?,?,?, strftime('%Y-%m-%d %H:%M:%f','now'))`)
 | |
|       .run('g1@g.us', 'comm-1', 'Grupo 1', 1);
 | |
|   });
 | |
| 
 | |
|   afterEach(() => {
 | |
|     memdb.close();
 | |
|     process.env = envBackup;
 | |
|   });
 | |
| 
 | |
|   it('publica prompt cuando coverage < 100, grace cumplido y sin cooldown', () => {
 | |
|     // snapshot con un resoluble (dígitos) y uno no resoluble (alias sin mapeo)
 | |
|     const res = GroupSyncService.reconcileGroupMembers('g1@g.us', [
 | |
|       { userId: '111', isAdmin: false },
 | |
|       { userId: 'alias_lid', isAdmin: false }
 | |
|     ], '2025-01-01 00:00:00.000');
 | |
| 
 | |
|     expect(res).toEqual(expect.objectContaining({ added: 2 }));
 | |
|     const row = memdb.query(`SELECT recipient, message, status FROM response_queue ORDER BY id DESC LIMIT 1`).get() as any;
 | |
|     expect(row).toBeTruthy();
 | |
|     expect(row.recipient).toBe('g1@g.us');
 | |
|     expect(String(row.message)).toContain('https://wa.me/555111222');
 | |
| 
 | |
|     const g = memdb.query(`SELECT onboarding_prompted_at FROM groups WHERE id = 'g1@g.us'`).get() as any;
 | |
|     expect(g).toBeTruthy();
 | |
|     expect(g.onboarding_prompted_at).toBeTruthy();
 | |
|   });
 | |
| 
 | |
|   it('omite prompt cuando coverage = 100', () => {
 | |
|     // Previo: no debe existir prompt para este grupo
 | |
|     const before = memdb.query(`SELECT COUNT(*) AS c FROM response_queue`).get() as any;
 | |
|     expect(Number(before.c)).toBe(0);
 | |
| 
 | |
|     // snapshot totalmente resoluble (dos dígitos)
 | |
|     GroupSyncService.reconcileGroupMembers('g1@g.us', [
 | |
|       { userId: '111', isAdmin: false },
 | |
|       { userId: '222', isAdmin: false }
 | |
|     ], '2025-01-01 00:00:00.000');
 | |
| 
 | |
|     const after = memdb.query(`SELECT COUNT(*) AS c FROM response_queue`).get() as any;
 | |
|     expect(Number(after.c)).toBe(0);
 | |
|   });
 | |
| 
 | |
|   it('omite prompt en modo enforce si el grupo no está allowed', () => {
 | |
|     process.env.GROUP_GATING_MODE = 'enforce';
 | |
|     AllowedGroups.setStatus('g1@g.us', 'blocked');
 | |
| 
 | |
|     GroupSyncService.reconcileGroupMembers('g1@g.us', [
 | |
|       { userId: '111', isAdmin: false },
 | |
|       { userId: 'alias_lid', isAdmin: false }
 | |
|     ], '2025-01-01 00:00:00.000');
 | |
| 
 | |
|     const count = memdb.query(`SELECT COUNT(*) AS c FROM response_queue`).get() as any;
 | |
|     expect(Number(count.c)).toBe(0);
 | |
|   });
 | |
| });
 |