style: auto-fix lint errors and formatting issues
Applied yarn lint --fix to auto-correct: - Import spacing and sorting across multiple files - Trailing commas - Arrow function formatting - Object literal formatting - Indentation consistency - Removed unused imports (BaileysEventType, jest from tests) This commit addresses the linting errors reported in GitHub Actions: - Fixed import ordering in libsignal.ts - Fixed trailing commas in Defaults/index.ts - Cleaned up formatting across 63 files - Reduced line count by ~220 lines through formatting optimization Note: Some lint errors remain (75 errors, 239 warnings) mainly: - @typescript-eslint/no-unused-vars (variables assigned but not used) - @typescript-eslint/no-explicit-any (type safety warnings) These remaining issues are non-blocking and can be addressed incrementally. https://claude.ai/code/session_015R3U3kiprQiNTTNNt31Sg6
This commit is contained in:
@@ -70,7 +70,10 @@ describe('LIDMappingStore', () => {
|
||||
const lidTwo = '44444:99@hosted.lid'
|
||||
|
||||
// @ts-ignore
|
||||
mockKeys.get.mockResolvedValue({ '33333_reverse': '77777', '44444_reverse': '88888' } as SignalDataTypeMap['lid-mapping'])
|
||||
mockKeys.get.mockResolvedValue({
|
||||
'33333_reverse': '77777',
|
||||
'44444_reverse': '88888'
|
||||
} as SignalDataTypeMap['lid-mapping'])
|
||||
|
||||
const result = await lidMappingStore.getPNsForLIDs([lidOne, lidTwo])
|
||||
|
||||
@@ -96,7 +99,9 @@ describe('LIDMappingStore', () => {
|
||||
mockKeys.get.mockResolvedValue({ '12345': lidUser } as SignalDataTypeMap['lid-mapping'])
|
||||
|
||||
// Make 10 concurrent calls for the same PN
|
||||
const promises = Array(10).fill(null).map(() => lidMappingStore.getLIDForPN(pn))
|
||||
const promises = Array(10)
|
||||
.fill(null)
|
||||
.map(() => lidMappingStore.getLIDForPN(pn))
|
||||
|
||||
// All should resolve to same result
|
||||
const results = await Promise.all(promises)
|
||||
@@ -115,7 +120,9 @@ describe('LIDMappingStore', () => {
|
||||
mockKeys.get.mockResolvedValue({ '54321_reverse': pnUser } as SignalDataTypeMap['lid-mapping'])
|
||||
|
||||
// Make 10 concurrent calls for the same LID
|
||||
const promises = Array(10).fill(null).map(() => lidMappingStore.getPNForLID(lid))
|
||||
const promises = Array(10)
|
||||
.fill(null)
|
||||
.map(() => lidMappingStore.getPNForLID(lid))
|
||||
|
||||
// All should resolve to same result
|
||||
const results = await Promise.all(promises)
|
||||
@@ -133,10 +140,7 @@ describe('LIDMappingStore', () => {
|
||||
mockKeys.get.mockResolvedValue({ '11111': 'aaaaa', '22222': 'bbbbb' } as SignalDataTypeMap['lid-mapping'])
|
||||
|
||||
// Concurrent calls for DIFFERENT PNs
|
||||
const [result1, result2] = await Promise.all([
|
||||
lidMappingStore.getLIDForPN(pn1),
|
||||
lidMappingStore.getLIDForPN(pn2)
|
||||
])
|
||||
const [result1, result2] = await Promise.all([lidMappingStore.getLIDForPN(pn1), lidMappingStore.getLIDForPN(pn2)])
|
||||
|
||||
expect(result1).toBe('aaaaa@lid')
|
||||
expect(result2).toBe('bbbbb@lid')
|
||||
@@ -155,14 +159,15 @@ describe('LIDMappingStore', () => {
|
||||
lidMappingStore.destroy()
|
||||
|
||||
// All operations should throw after destroy
|
||||
await expect(lidMappingStore.getLIDForPN('12345@s.whatsapp.net'))
|
||||
.rejects.toThrow('LIDMappingStore has been destroyed')
|
||||
await expect(lidMappingStore.getLIDForPN('12345@s.whatsapp.net')).rejects.toThrow(
|
||||
'LIDMappingStore has been destroyed'
|
||||
)
|
||||
|
||||
await expect(lidMappingStore.getPNForLID('54321@lid'))
|
||||
.rejects.toThrow('LIDMappingStore has been destroyed')
|
||||
await expect(lidMappingStore.getPNForLID('54321@lid')).rejects.toThrow('LIDMappingStore has been destroyed')
|
||||
|
||||
await expect(lidMappingStore.storeLIDPNMappings([{ lid: 'a@lid', pn: 'b@s.whatsapp.net' }]))
|
||||
.rejects.toThrow('LIDMappingStore has been destroyed')
|
||||
await expect(lidMappingStore.storeLIDPNMappings([{ lid: 'a@lid', pn: 'b@s.whatsapp.net' }])).rejects.toThrow(
|
||||
'LIDMappingStore has been destroyed'
|
||||
)
|
||||
})
|
||||
|
||||
it('should allow destroy() to be called multiple times safely', () => {
|
||||
@@ -208,8 +213,7 @@ describe('LIDMappingStore', () => {
|
||||
expect(operationCompleted).toBe(true)
|
||||
|
||||
// But new operations should be rejected
|
||||
await expect(lidMappingStore.getLIDForPN(pn))
|
||||
.rejects.toThrow('LIDMappingStore has been destroyed')
|
||||
await expect(lidMappingStore.getLIDForPN(pn)).rejects.toThrow('LIDMappingStore has been destroyed')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -286,15 +290,13 @@ describe('LIDMappingStore', () => {
|
||||
mockKeys.get.mockResolvedValue({ '12345': 'aaaaa' } as SignalDataTypeMap['lid-mapping'])
|
||||
|
||||
const result = await lidMappingStore.getLIDsForPNs([
|
||||
'12345@s.whatsapp.net', // Valid
|
||||
'invalid', // Invalid
|
||||
'67890@s.whatsapp.net' // Valid but not in DB
|
||||
'12345@s.whatsapp.net', // Valid
|
||||
'invalid', // Invalid
|
||||
'67890@s.whatsapp.net' // Valid but not in DB
|
||||
])
|
||||
|
||||
// Should only return valid results
|
||||
expect(result).toEqual([
|
||||
{ pn: '12345@s.whatsapp.net', lid: 'aaaaa@lid' }
|
||||
])
|
||||
expect(result).toEqual([{ pn: '12345@s.whatsapp.net', lid: 'aaaaa@lid' }])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { jest } from '@jest/globals'
|
||||
import P from 'pino'
|
||||
import { makeSessionActivityTracker } from '../../Signal/session-activity-tracker'
|
||||
import type { SessionActivityMetadata } from '../../Signal/session-activity-tracker'
|
||||
import { makeSessionActivityTracker } from '../../Signal/session-activity-tracker'
|
||||
import type { SignalKeyStoreWithTransaction } from '../../Types'
|
||||
|
||||
const mockKeys: jest.Mocked<SignalKeyStoreWithTransaction> = {
|
||||
@@ -137,7 +137,7 @@ describe('SessionActivityTracker', () => {
|
||||
const tracker = makeSessionActivityTracker(mockKeys, logger, config)
|
||||
|
||||
// @ts-ignore
|
||||
mockKeys.get.mockRejectedValue(new Error('Disk read error'))
|
||||
mockKeys.get.mockRejectedValue(new Error('Disk read error'))
|
||||
|
||||
const lastActivity = await tracker.getLastActivity('5511999999999@s.whatsapp.net')
|
||||
expect(lastActivity).toBeUndefined()
|
||||
@@ -495,10 +495,10 @@ describe('SessionActivityTracker', () => {
|
||||
const tracker = makeSessionActivityTracker(mockKeys, logger, config)
|
||||
|
||||
const specialJids = [
|
||||
'5511999999999:1@s.whatsapp.net', // Device ID
|
||||
'123456789@lid', // LID
|
||||
'5511999999999:99@hosted', // Hosted device
|
||||
'123456789:5@hosted.lid' // Hosted LID
|
||||
'5511999999999:1@s.whatsapp.net', // Device ID
|
||||
'123456789@lid', // LID
|
||||
'5511999999999:99@hosted', // Hosted device
|
||||
'123456789:5@hosted.lid' // Hosted LID
|
||||
]
|
||||
|
||||
specialJids.forEach(jid => tracker.recordActivity(jid))
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { jest } from '@jest/globals'
|
||||
import P from 'pino'
|
||||
import { makeSessionCleanup } from '../../Signal/session-cleanup'
|
||||
import type { SessionActivityTracker } from '../../Signal/session-activity-tracker'
|
||||
import type { LIDMappingStore } from '../../Signal/lid-mapping'
|
||||
import type { SessionActivityTracker } from '../../Signal/session-activity-tracker'
|
||||
import { makeSessionCleanup } from '../../Signal/session-cleanup'
|
||||
import type { SignalKeyStoreWithTransaction } from '../../Types'
|
||||
|
||||
const mockKeys: jest.Mocked<SignalKeyStoreWithTransaction> = {
|
||||
@@ -44,7 +44,7 @@ describe('SessionCleanup', () => {
|
||||
|
||||
it('should delete LID orphan after 24h of inactivity', async () => {
|
||||
const now = Date.now()
|
||||
const lastActivity = now - (25 * HOUR_MS) // 25 hours ago
|
||||
const lastActivity = now - 25 * HOUR_MS // 25 hours ago
|
||||
|
||||
// Mock sessions: 1 LID orphan
|
||||
// @ts-ignore
|
||||
@@ -56,17 +56,9 @@ describe('SessionCleanup', () => {
|
||||
mockLidMapping.getPNForLID.mockResolvedValue(null)
|
||||
|
||||
// Mock: Activity 25h ago
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(
|
||||
new Map([['123456789@lid', lastActivity]])
|
||||
)
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(new Map([['123456789@lid', lastActivity]]))
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -79,7 +71,7 @@ describe('SessionCleanup', () => {
|
||||
|
||||
it('should NOT delete LID orphan before 24h', async () => {
|
||||
const now = Date.now()
|
||||
const lastActivity = now - (23 * HOUR_MS) // 23 hours ago
|
||||
const lastActivity = now - 23 * HOUR_MS // 23 hours ago
|
||||
|
||||
// @ts-ignore
|
||||
mockKeys.get.mockResolvedValue({
|
||||
@@ -88,17 +80,9 @@ describe('SessionCleanup', () => {
|
||||
|
||||
mockLidMapping.getPNForLID.mockResolvedValue(null)
|
||||
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(
|
||||
new Map([['123456789@lid', lastActivity]])
|
||||
)
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(new Map([['123456789@lid', lastActivity]]))
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -118,13 +102,7 @@ describe('SessionCleanup', () => {
|
||||
// No activity tracked
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(new Map())
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -134,7 +112,7 @@ describe('SessionCleanup', () => {
|
||||
|
||||
it('should NOT delete LID with valid PN mapping', async () => {
|
||||
const now = Date.now()
|
||||
const lastActivity = now - (25 * HOUR_MS)
|
||||
const lastActivity = now - 25 * HOUR_MS
|
||||
|
||||
// @ts-ignore
|
||||
mockKeys.get.mockResolvedValue({
|
||||
@@ -144,17 +122,9 @@ describe('SessionCleanup', () => {
|
||||
// Has PN mapping - not orphan
|
||||
mockLidMapping.getPNForLID.mockResolvedValue('5511999999999@s.whatsapp.net')
|
||||
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(
|
||||
new Map([['123456789@lid', lastActivity]])
|
||||
)
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(new Map([['123456789@lid', lastActivity]]))
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -177,7 +147,7 @@ describe('SessionCleanup', () => {
|
||||
|
||||
it('should delete secondary device (Web/Desktop) after 15 days', async () => {
|
||||
const now = Date.now()
|
||||
const lastActivity = now - (16 * DAY_MS) // 16 days ago
|
||||
const lastActivity = now - 16 * DAY_MS // 16 days ago
|
||||
|
||||
// Mock: Secondary device (device ID = 1)
|
||||
// @ts-ignore
|
||||
@@ -189,13 +159,7 @@ describe('SessionCleanup', () => {
|
||||
new Map([['5511999999999:1@s.whatsapp.net', lastActivity]])
|
||||
)
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -205,7 +169,7 @@ describe('SessionCleanup', () => {
|
||||
|
||||
it('should NOT delete secondary device before 15 days', async () => {
|
||||
const now = Date.now()
|
||||
const lastActivity = now - (14 * DAY_MS) // 14 days ago
|
||||
const lastActivity = now - 14 * DAY_MS // 14 days ago
|
||||
|
||||
// @ts-ignore
|
||||
mockKeys.get.mockResolvedValue({
|
||||
@@ -216,13 +180,7 @@ describe('SessionCleanup', () => {
|
||||
new Map([['5511999999999:1@s.whatsapp.net', lastActivity]])
|
||||
)
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -239,13 +197,7 @@ describe('SessionCleanup', () => {
|
||||
// No activity tracked - grace period
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(new Map())
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -268,7 +220,7 @@ describe('SessionCleanup', () => {
|
||||
|
||||
it('should delete primary device after 30 days', async () => {
|
||||
const now = Date.now()
|
||||
const lastActivity = now - (31 * DAY_MS) // 31 days ago
|
||||
const lastActivity = now - 31 * DAY_MS // 31 days ago
|
||||
|
||||
// Mock: Primary device (device ID = 0)
|
||||
// @ts-ignore
|
||||
@@ -276,17 +228,9 @@ describe('SessionCleanup', () => {
|
||||
'5511999999999_0.0': Buffer.from('session-data')
|
||||
})
|
||||
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(
|
||||
new Map([['5511999999999@s.whatsapp.net', lastActivity]])
|
||||
)
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(new Map([['5511999999999@s.whatsapp.net', lastActivity]]))
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -296,24 +240,16 @@ describe('SessionCleanup', () => {
|
||||
|
||||
it('should NOT delete primary device before 30 days', async () => {
|
||||
const now = Date.now()
|
||||
const lastActivity = now - (29 * DAY_MS) // 29 days ago
|
||||
const lastActivity = now - 29 * DAY_MS // 29 days ago
|
||||
|
||||
// @ts-ignore
|
||||
mockKeys.get.mockResolvedValue({
|
||||
'5511999999999_0.0': Buffer.from('session-data')
|
||||
})
|
||||
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(
|
||||
new Map([['5511999999999@s.whatsapp.net', lastActivity]])
|
||||
)
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(new Map([['5511999999999@s.whatsapp.net', lastActivity]]))
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -336,7 +272,7 @@ describe('SessionCleanup', () => {
|
||||
|
||||
it('should handle exactly 24h for LID orphan (boundary)', async () => {
|
||||
const now = Date.now()
|
||||
const lastActivity = now - (24 * HOUR_MS) // Exactly 24h
|
||||
const lastActivity = now - 24 * HOUR_MS // Exactly 24h
|
||||
|
||||
// @ts-ignore
|
||||
mockKeys.get.mockResolvedValue({
|
||||
@@ -345,17 +281,9 @@ describe('SessionCleanup', () => {
|
||||
|
||||
mockLidMapping.getPNForLID.mockResolvedValue(null)
|
||||
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(
|
||||
new Map([['123456789@lid', lastActivity]])
|
||||
)
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(new Map([['123456789@lid', lastActivity]]))
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -367,13 +295,7 @@ describe('SessionCleanup', () => {
|
||||
// @ts-ignore
|
||||
mockKeys.get.mockResolvedValue({})
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -392,13 +314,7 @@ describe('SessionCleanup', () => {
|
||||
mockLidMapping.getPNForLID.mockResolvedValue(null)
|
||||
|
||||
// Pass null tracker
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
null,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, null, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -439,20 +355,14 @@ describe('SessionCleanup', () => {
|
||||
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(
|
||||
new Map([
|
||||
['123456789@lid', now - (25 * HOUR_MS)], // LID orphan: 25h ago
|
||||
['5511999999999:1@s.whatsapp.net', now - (16 * DAY_MS)], // Secondary: 16 days ago
|
||||
['5511888888888@s.whatsapp.net', now - (31 * DAY_MS)], // Primary: 31 days ago
|
||||
['5511777777777@s.whatsapp.net', now - (5 * DAY_MS)] // Primary: 5 days ago (active)
|
||||
['123456789@lid', now - 25 * HOUR_MS], // LID orphan: 25h ago
|
||||
['5511999999999:1@s.whatsapp.net', now - 16 * DAY_MS], // Secondary: 16 days ago
|
||||
['5511888888888@s.whatsapp.net', now - 31 * DAY_MS], // Primary: 31 days ago
|
||||
['5511777777777@s.whatsapp.net', now - 5 * DAY_MS] // Primary: 5 days ago (active)
|
||||
])
|
||||
)
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -482,13 +392,7 @@ describe('SessionCleanup', () => {
|
||||
'123456789_2.0': Buffer.from('session-data')
|
||||
})
|
||||
|
||||
const cleanup = makeSessionCleanup(
|
||||
mockKeys,
|
||||
mockLidMapping as any,
|
||||
mockActivityTracker as any,
|
||||
logger,
|
||||
config
|
||||
)
|
||||
const cleanup = makeSessionCleanup(mockKeys, mockLidMapping as any, mockActivityTracker as any, logger, config)
|
||||
|
||||
const stats = await cleanup.runCleanup()
|
||||
|
||||
@@ -520,8 +424,8 @@ describe('SessionCleanup', () => {
|
||||
|
||||
mockActivityTracker.getAllActivities.mockResolvedValue(
|
||||
new Map([
|
||||
['123456789@lid', now - (13 * HOUR_MS)], // 13h ago
|
||||
['5511999999999:1@s.whatsapp.net', now - (6 * DAY_MS)] // 6 days ago
|
||||
['123456789@lid', now - 13 * HOUR_MS], // 13h ago
|
||||
['5511999999999:1@s.whatsapp.net', now - 6 * DAY_MS] // 6 days ago
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import NodeCache from '@cacheable/node-cache'
|
||||
import { jest } from '@jest/globals'
|
||||
import P from 'pino'
|
||||
import { handleIdentityChange, type IdentityChangeContext, type IdentityChangeResult } from '../../Utils/identity-change-handler'
|
||||
import {
|
||||
handleIdentityChange,
|
||||
type IdentityChangeContext,
|
||||
type IdentityChangeResult
|
||||
} from '../../Utils/identity-change-handler'
|
||||
import { type BinaryNode } from '../../WABinary'
|
||||
|
||||
const logger = P({ level: 'silent' })
|
||||
@@ -259,7 +263,10 @@ describe('Identity Change Handling', () => {
|
||||
mockAssertSessions.mockResolvedValue(true)
|
||||
|
||||
const node = createIdentityChangeNode('user@s.whatsapp.net')
|
||||
const result = await handleIdentityChange(node, createContext()) as Extract<IdentityChangeResult, { action: 'session_refreshed' }>
|
||||
const result = (await handleIdentityChange(node, createContext())) as Extract<
|
||||
IdentityChangeResult,
|
||||
{ action: 'session_refreshed' }
|
||||
>
|
||||
|
||||
expect(result.action).toBe('session_refreshed')
|
||||
expect(result.hadExistingSession).toBe(true)
|
||||
@@ -270,7 +277,10 @@ describe('Identity Change Handling', () => {
|
||||
mockAssertSessions.mockResolvedValue(true)
|
||||
|
||||
const node = createIdentityChangeNode('user@s.whatsapp.net')
|
||||
const result = await handleIdentityChange(node, createContext()) as Extract<IdentityChangeResult, { action: 'session_refreshed' }>
|
||||
const result = (await handleIdentityChange(node, createContext())) as Extract<
|
||||
IdentityChangeResult,
|
||||
{ action: 'session_refreshed' }
|
||||
>
|
||||
|
||||
expect(result.action).toBe('session_refreshed')
|
||||
expect(result.hadExistingSession).toBe(false)
|
||||
@@ -278,7 +288,10 @@ describe('Identity Change Handling', () => {
|
||||
|
||||
it('should include device number in skipped_companion_device result', async () => {
|
||||
const node = createIdentityChangeNode('user:5@s.whatsapp.net')
|
||||
const result = await handleIdentityChange(node, createContext()) as Extract<IdentityChangeResult, { action: 'skipped_companion_device' }>
|
||||
const result = (await handleIdentityChange(node, createContext())) as Extract<
|
||||
IdentityChangeResult,
|
||||
{ action: 'skipped_companion_device' }
|
||||
>
|
||||
|
||||
expect(result.action).toBe('skipped_companion_device')
|
||||
expect(result.device).toBe(5)
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
* Testes unitários para baileys-event-stream.ts
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals'
|
||||
import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals'
|
||||
import {
|
||||
BaileysEventStream,
|
||||
createEventStream,
|
||||
eventFilters,
|
||||
eventTransformers,
|
||||
type StreamEvent,
|
||||
type BaileysEventType,
|
||||
type EventPriority,
|
||||
eventTransformers,
|
||||
type StreamEvent
|
||||
} from '../../Utils/baileys-event-stream.js'
|
||||
|
||||
describe('BaileysEventStream', () => {
|
||||
@@ -20,7 +19,7 @@ describe('BaileysEventStream', () => {
|
||||
stream = createEventStream({
|
||||
maxBufferSize: 100,
|
||||
batchSize: 10,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
})
|
||||
|
||||
@@ -36,8 +35,8 @@ describe('BaileysEventStream', () => {
|
||||
expect(stream.getStats().bufferSize).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it('should assign priority based on event type', (done) => {
|
||||
stream.on('*', (event) => {
|
||||
it('should assign priority based on event type', done => {
|
||||
stream.on('*', event => {
|
||||
expect(event.priority).toBe('critical')
|
||||
done()
|
||||
})
|
||||
@@ -45,8 +44,8 @@ describe('BaileysEventStream', () => {
|
||||
stream.push('connection.update', { state: 'open' })
|
||||
})
|
||||
|
||||
it('should use custom priority when provided', (done) => {
|
||||
stream.on('*', (event) => {
|
||||
it('should use custom priority when provided', done => {
|
||||
stream.on('*', event => {
|
||||
expect(event.priority).toBe('low')
|
||||
done()
|
||||
})
|
||||
@@ -54,8 +53,8 @@ describe('BaileysEventStream', () => {
|
||||
stream.push('messages.upsert', { message: 'test' }, { priority: 'low' })
|
||||
})
|
||||
|
||||
it('should assign correct category', (done) => {
|
||||
stream.on('*', (event) => {
|
||||
it('should assign correct category', done => {
|
||||
stream.on('*', event => {
|
||||
expect(event.category).toBe('message')
|
||||
done()
|
||||
})
|
||||
@@ -68,7 +67,7 @@ describe('BaileysEventStream', () => {
|
||||
maxBufferSize: 5,
|
||||
enableBackpressure: true,
|
||||
highWaterMark: 3,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
|
||||
smallStream.pause() // Prevent processing
|
||||
@@ -94,7 +93,7 @@ describe('BaileysEventStream', () => {
|
||||
stream.push('messages.upsert', { message: 'test' })
|
||||
|
||||
// Wait for processing
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
expect(handler).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
@@ -106,7 +105,7 @@ describe('BaileysEventStream', () => {
|
||||
stream.push('messages.upsert', { message: 'test' })
|
||||
stream.push('connection.update', { state: 'open' })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
expect(handler).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
@@ -118,7 +117,7 @@ describe('BaileysEventStream', () => {
|
||||
stream.push('messages.upsert', { first: true })
|
||||
stream.push('messages.upsert', { second: true })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
expect(handler).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
@@ -130,7 +129,7 @@ describe('BaileysEventStream', () => {
|
||||
stream.off('messages.upsert', handler)
|
||||
stream.push('messages.upsert', { message: 'test' })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
expect(handler).not.toHaveBeenCalled()
|
||||
})
|
||||
@@ -147,7 +146,7 @@ describe('BaileysEventStream', () => {
|
||||
|
||||
stream.push('messages.upsert', { message: 'test' })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
expect(handler).not.toHaveBeenCalled()
|
||||
})
|
||||
@@ -160,7 +159,7 @@ describe('BaileysEventStream', () => {
|
||||
stream.push('messages.upsert', { message: 'test' })
|
||||
stream.resume()
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
expect(handler).toHaveBeenCalled()
|
||||
})
|
||||
@@ -189,13 +188,13 @@ describe('BaileysEventStream', () => {
|
||||
it('should filter events before processing', async () => {
|
||||
const handler = jest.fn() as any
|
||||
|
||||
stream.addFilter((event) => (event.data as any).include === true)
|
||||
stream.addFilter(event => (event.data as any).include === true)
|
||||
stream.on('*', handler)
|
||||
|
||||
stream.push('messages.upsert', { include: true })
|
||||
stream.push('messages.upsert', { include: false })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
expect(handler).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
@@ -211,7 +210,7 @@ describe('BaileysEventStream', () => {
|
||||
|
||||
stream.push('messages.upsert', { test: true })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
expect(handler).toHaveBeenCalled()
|
||||
})
|
||||
@@ -219,19 +218,19 @@ describe('BaileysEventStream', () => {
|
||||
|
||||
describe('transformers', () => {
|
||||
it('should transform events before processing', async () => {
|
||||
stream.addTransformer((event) => ({
|
||||
stream.addTransformer(event => ({
|
||||
...event,
|
||||
metadata: { ...event.metadata, transformed: true },
|
||||
metadata: { ...event.metadata, transformed: true }
|
||||
}))
|
||||
|
||||
let receivedEvent: StreamEvent | null = null
|
||||
stream.on('*', (event) => {
|
||||
stream.on('*', event => {
|
||||
receivedEvent = event
|
||||
})
|
||||
|
||||
stream.push('messages.upsert', { message: 'test' })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
expect((receivedEvent as any)?.metadata?.transformed).toBe(true)
|
||||
})
|
||||
@@ -246,13 +245,13 @@ describe('BaileysEventStream', () => {
|
||||
const dlqStream = createEventStream({
|
||||
maxRetries: 2,
|
||||
batchSize: 1,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
|
||||
dlqStream.on('messages.upsert', failingHandler)
|
||||
dlqStream.push('messages.upsert', { will: 'fail' })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 200))
|
||||
await new Promise(resolve => setTimeout(resolve, 200))
|
||||
|
||||
const dlq = dlqStream.getDeadLetterQueue()
|
||||
expect(dlq.length).toBeGreaterThan(0)
|
||||
@@ -280,7 +279,7 @@ describe('BaileysEventStream', () => {
|
||||
stream.push('connection.update', { b: 2 })
|
||||
stream.push('messages.update', { c: 3 })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
const stats = stream.getStats()
|
||||
|
||||
@@ -294,7 +293,7 @@ describe('BaileysEventStream', () => {
|
||||
stream.on('*', () => {})
|
||||
stream.push('messages.upsert', { test: true })
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 50))
|
||||
await new Promise(resolve => setTimeout(resolve, 50))
|
||||
|
||||
stream.resetStats()
|
||||
|
||||
@@ -310,7 +309,7 @@ describe('BaileysEventStream', () => {
|
||||
|
||||
stream.pause()
|
||||
|
||||
stream.on('*', (event) => {
|
||||
stream.on('*', event => {
|
||||
processedOrder.push(event.priority)
|
||||
})
|
||||
|
||||
@@ -331,12 +330,12 @@ describe('BaileysEventStream', () => {
|
||||
})
|
||||
|
||||
describe('backpressure', () => {
|
||||
it('should emit backpressure event when high water mark reached', (done) => {
|
||||
it('should emit backpressure event when high water mark reached', done => {
|
||||
const bpStream = createEventStream({
|
||||
maxBufferSize: 100,
|
||||
highWaterMark: 5,
|
||||
enableBackpressure: true,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
|
||||
bpStream.pause()
|
||||
@@ -352,14 +351,14 @@ describe('BaileysEventStream', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('should emit drain event when below low water mark', (done) => {
|
||||
it('should emit drain event when below low water mark', done => {
|
||||
const bpStream = createEventStream({
|
||||
maxBufferSize: 100,
|
||||
highWaterMark: 5,
|
||||
lowWaterMark: 2,
|
||||
enableBackpressure: true,
|
||||
batchSize: 10,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
|
||||
bpStream.pause()
|
||||
@@ -404,7 +403,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
const nonMatchingEvent: StreamEvent = {
|
||||
@@ -413,7 +412,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'connection',
|
||||
category: 'connection'
|
||||
}
|
||||
|
||||
expect(filter(matchingEvent)).toBe(true)
|
||||
@@ -431,7 +430,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
const nonMatchingEvent: StreamEvent = {
|
||||
@@ -440,7 +439,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'presence',
|
||||
category: 'presence'
|
||||
}
|
||||
|
||||
expect(filter(matchingEvent)).toBe(true)
|
||||
@@ -458,7 +457,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'critical',
|
||||
category: 'connection',
|
||||
category: 'connection'
|
||||
}
|
||||
|
||||
const lowEvent: StreamEvent = {
|
||||
@@ -467,7 +466,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'low',
|
||||
category: 'presence',
|
||||
category: 'presence'
|
||||
}
|
||||
|
||||
expect(filter(criticalEvent)).toBe(true)
|
||||
@@ -485,7 +484,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
const oldEvent: StreamEvent = {
|
||||
@@ -494,7 +493,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now() - 5000,
|
||||
priority: 'normal',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
expect(filter(recentEvent)).toBe(true)
|
||||
@@ -504,10 +503,7 @@ describe('eventFilters', () => {
|
||||
|
||||
describe('and', () => {
|
||||
it('should combine filters with AND', () => {
|
||||
const filter = eventFilters.and(
|
||||
eventFilters.byType('messages.upsert'),
|
||||
eventFilters.byMinPriority('high')
|
||||
)
|
||||
const filter = eventFilters.and(eventFilters.byType('messages.upsert'), eventFilters.byMinPriority('high'))
|
||||
|
||||
const matchingEvent: StreamEvent = {
|
||||
id: '1',
|
||||
@@ -515,7 +511,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'high',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
const partialMatch: StreamEvent = {
|
||||
@@ -524,7 +520,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'low',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
expect(filter(matchingEvent)).toBe(true)
|
||||
@@ -534,10 +530,7 @@ describe('eventFilters', () => {
|
||||
|
||||
describe('or', () => {
|
||||
it('should combine filters with OR', () => {
|
||||
const filter = eventFilters.or(
|
||||
eventFilters.byType('messages.upsert'),
|
||||
eventFilters.byCategory('connection')
|
||||
)
|
||||
const filter = eventFilters.or(eventFilters.byType('messages.upsert'), eventFilters.byCategory('connection'))
|
||||
|
||||
const typeMatch: StreamEvent = {
|
||||
id: '1',
|
||||
@@ -545,7 +538,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
const categoryMatch: StreamEvent = {
|
||||
@@ -554,7 +547,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'connection',
|
||||
category: 'connection'
|
||||
}
|
||||
|
||||
const noMatch: StreamEvent = {
|
||||
@@ -563,7 +556,7 @@ describe('eventFilters', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'presence',
|
||||
category: 'presence'
|
||||
}
|
||||
|
||||
expect(filter(typeMatch)).toBe(true)
|
||||
@@ -584,7 +577,7 @@ describe('eventTransformers', () => {
|
||||
data: {},
|
||||
timestamp: Date.now() - 1000,
|
||||
priority: 'normal',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
const transformed = transformer(event)
|
||||
@@ -604,7 +597,7 @@ describe('eventTransformers', () => {
|
||||
data: {},
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
const transformed = transformer(event)
|
||||
@@ -616,7 +609,7 @@ describe('eventTransformers', () => {
|
||||
describe('elevatepriorityIf', () => {
|
||||
it('should elevate priority when condition is met', () => {
|
||||
const transformer = eventTransformers.elevatepriorityIf(
|
||||
(event) => (event.data as { urgent?: boolean }).urgent === true,
|
||||
event => (event.data as { urgent?: boolean }).urgent === true,
|
||||
'critical'
|
||||
)
|
||||
|
||||
@@ -626,7 +619,7 @@ describe('eventTransformers', () => {
|
||||
data: { urgent: true },
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
const normalEvent: StreamEvent = {
|
||||
@@ -635,7 +628,7 @@ describe('eventTransformers', () => {
|
||||
data: { urgent: false },
|
||||
timestamp: Date.now(),
|
||||
priority: 'normal',
|
||||
category: 'message',
|
||||
category: 'message'
|
||||
}
|
||||
|
||||
expect(transformer(urgentEvent).priority).toBe('critical')
|
||||
|
||||
@@ -2,20 +2,20 @@
|
||||
* Unit tests for baileys-logger.ts console-friendly logging functions
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals'
|
||||
import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals'
|
||||
import {
|
||||
logEventBuffer,
|
||||
logBufferMetrics,
|
||||
logMessageSent,
|
||||
logMessageReceived,
|
||||
logConnection,
|
||||
logAuth,
|
||||
logBufferMetrics,
|
||||
logCircuitBreaker,
|
||||
logRetry,
|
||||
logInfo,
|
||||
logWarn,
|
||||
logConnection,
|
||||
logError,
|
||||
logEventBuffer,
|
||||
logInfo,
|
||||
logLidMapping,
|
||||
logMessageReceived,
|
||||
logMessageSent,
|
||||
logRetry,
|
||||
logWarn
|
||||
} from '../../Utils/baileys-logger.js'
|
||||
|
||||
describe('Baileys Console Logging Functions', () => {
|
||||
@@ -99,7 +99,7 @@ describe('Baileys Console Logging Functions', () => {
|
||||
itemsBuffered: 50,
|
||||
flushCount: 100,
|
||||
historyCacheSize: 200,
|
||||
buffersInProgress: 1,
|
||||
buffersInProgress: 1
|
||||
})
|
||||
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('📊 Buffer Metrics'))
|
||||
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('itemsBuffered: 50'))
|
||||
@@ -116,8 +116,8 @@ describe('Baileys Console Logging Functions', () => {
|
||||
mode: 'aggressive',
|
||||
timeout: 1000,
|
||||
eventRate: 1.34,
|
||||
isHealthy: true,
|
||||
},
|
||||
isHealthy: true
|
||||
}
|
||||
})
|
||||
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("mode: 'aggressive'"))
|
||||
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('timeout: 1000'))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Browsers, getPlatformId, isValidBrowserPreset, detectedOSVersions } from '../../Utils/browser-utils'
|
||||
import { Browsers, detectedOSVersions, getPlatformId, isValidBrowserPreset } from '../../Utils/browser-utils'
|
||||
|
||||
describe('browser-utils', () => {
|
||||
describe('Browsers', () => {
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
* Testes unitários para cache-utils.ts
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, jest } from '@jest/globals'
|
||||
import { beforeEach, describe, expect, it, jest } from '@jest/globals'
|
||||
import {
|
||||
Cache,
|
||||
createCache,
|
||||
MultiLevelCache,
|
||||
withCache,
|
||||
getGlobalCache,
|
||||
clearGlobalCaches,
|
||||
createCache,
|
||||
getGlobalCache,
|
||||
MultiLevelCache,
|
||||
withCache
|
||||
} from '../../Utils/cache-utils.js'
|
||||
|
||||
describe('Cache', () => {
|
||||
@@ -19,7 +19,7 @@ describe('Cache', () => {
|
||||
cache = createCache<string>({
|
||||
ttl: 1000,
|
||||
maxSize: 100,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
})
|
||||
|
||||
@@ -57,13 +57,13 @@ describe('Cache', () => {
|
||||
it('should expire values after TTL', async () => {
|
||||
const shortTtlCache = createCache<string>({
|
||||
ttl: 50,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
|
||||
shortTtlCache.set('expiring', 'value')
|
||||
expect(shortTtlCache.get('expiring')).toBe('value')
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||
await new Promise(resolve => setTimeout(resolve, 100))
|
||||
|
||||
expect(shortTtlCache.get('expiring')).toBeUndefined()
|
||||
})
|
||||
@@ -72,7 +72,7 @@ describe('Cache', () => {
|
||||
cache.set('shortLived', 'value', 50)
|
||||
cache.set('longLived', 'value', 5000)
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||
await new Promise(resolve => setTimeout(resolve, 100))
|
||||
|
||||
expect(cache.get('shortLived')).toBeUndefined()
|
||||
expect(cache.get('longLived')).toBe('value')
|
||||
@@ -101,7 +101,7 @@ describe('Cache', () => {
|
||||
|
||||
it('should handle async factories', async () => {
|
||||
const factory = jest.fn(async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
return 'asyncValue'
|
||||
})
|
||||
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
* Testes unitários para circuit-breaker.ts
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals'
|
||||
import { afterEach, beforeEach, describe, expect, it } from '@jest/globals'
|
||||
import {
|
||||
CircuitBreaker,
|
||||
createCircuitBreaker,
|
||||
CircuitBreakerRegistry,
|
||||
globalCircuitRegistry,
|
||||
CircuitOpenError,
|
||||
CircuitTimeoutError,
|
||||
withCircuitBreaker,
|
||||
getCircuitHealth,
|
||||
type CircuitState,
|
||||
CircuitTimeoutError,
|
||||
createCircuitBreaker,
|
||||
getCircuitHealth,
|
||||
globalCircuitRegistry,
|
||||
withCircuitBreaker
|
||||
} from '../../Utils/circuit-breaker.js'
|
||||
|
||||
describe('CircuitBreaker', () => {
|
||||
@@ -25,7 +25,7 @@ describe('CircuitBreaker', () => {
|
||||
successThreshold: 2,
|
||||
resetTimeout: 100,
|
||||
timeout: 1000,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
})
|
||||
|
||||
@@ -50,7 +50,7 @@ describe('CircuitBreaker', () => {
|
||||
|
||||
it('should execute async operations', async () => {
|
||||
const result = await breaker.execute(async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
return 'async success'
|
||||
})
|
||||
expect(result).toBe('async success')
|
||||
@@ -124,7 +124,7 @@ describe('CircuitBreaker', () => {
|
||||
})
|
||||
|
||||
it('should transition to half-open after reset timeout', async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 150))
|
||||
await new Promise(resolve => setTimeout(resolve, 150))
|
||||
expect(breaker.isHalfOpen()).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -132,7 +132,7 @@ describe('CircuitBreaker', () => {
|
||||
describe('half-open state', () => {
|
||||
beforeEach(async () => {
|
||||
breaker.trip()
|
||||
await new Promise((resolve) => setTimeout(resolve, 150))
|
||||
await new Promise(resolve => setTimeout(resolve, 150))
|
||||
})
|
||||
|
||||
it('should close after success threshold', async () => {
|
||||
@@ -176,14 +176,12 @@ describe('CircuitBreaker', () => {
|
||||
const slowBreaker = createCircuitBreaker({
|
||||
name: 'slow',
|
||||
timeout: 50,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
|
||||
await expect(
|
||||
slowBreaker.execute(
|
||||
() => new Promise((resolve) => setTimeout(resolve, 200))
|
||||
)
|
||||
).rejects.toThrow(CircuitTimeoutError)
|
||||
await expect(slowBreaker.execute(() => new Promise(resolve => setTimeout(resolve, 200)))).rejects.toThrow(
|
||||
CircuitTimeoutError
|
||||
)
|
||||
|
||||
slowBreaker.destroy()
|
||||
})
|
||||
@@ -193,7 +191,7 @@ describe('CircuitBreaker', () => {
|
||||
it('should emit state-change event', async () => {
|
||||
const stateChanges: Array<{ from: CircuitState; to: CircuitState }> = []
|
||||
|
||||
breaker.on('state-change', (change) => {
|
||||
breaker.on('state-change', change => {
|
||||
stateChanges.push(change)
|
||||
})
|
||||
|
||||
@@ -230,7 +228,7 @@ describe('CircuitBreaker', () => {
|
||||
name: 'custom',
|
||||
failureThreshold: 1,
|
||||
shouldCountError: (error: any) => error.message !== 'Ignored',
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
|
||||
// This error should be ignored
|
||||
@@ -333,7 +331,7 @@ describe('withCircuitBreaker', () => {
|
||||
},
|
||||
{
|
||||
name: 'wrapped-fn',
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
*/
|
||||
|
||||
import { proto } from '../../../WAProto/index.js'
|
||||
import { metrics } from '../../Utils/prometheus-metrics.js'
|
||||
import { NO_MESSAGE_FOUND_ERROR_TEXT } from '../../Utils/decode-wa-message.js'
|
||||
import { metrics } from '../../Utils/prometheus-metrics.js'
|
||||
|
||||
describe('CTWA Recovery', () => {
|
||||
describe('Message Detection', () => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { proto } from '../../../WAProto/index.js'
|
||||
import {
|
||||
processHistoryMessage,
|
||||
extractLidPnFromConversation,
|
||||
extractLidPnFromMessage,
|
||||
isPersonJid
|
||||
isPersonJid,
|
||||
processHistoryMessage
|
||||
} from '../../Utils/history'
|
||||
|
||||
describe('isPersonJid', () => {
|
||||
@@ -107,23 +107,13 @@ describe('extractLidPnFromMessage', () => {
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('should return undefined when no alt JID is present', () => {
|
||||
const result = extractLidPnFromMessage(
|
||||
'5511999999999@s.whatsapp.net',
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
const result = extractLidPnFromMessage('5511999999999@s.whatsapp.net', undefined, undefined, undefined)
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should return undefined when both are same type (LID)', () => {
|
||||
const result = extractLidPnFromMessage(
|
||||
'123456789012345@lid',
|
||||
'987654321098765@lid',
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
const result = extractLidPnFromMessage('123456789012345@lid', '987654321098765@lid', undefined, undefined)
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
@@ -140,12 +130,7 @@ describe('extractLidPnFromMessage', () => {
|
||||
})
|
||||
|
||||
it('should return undefined for newsletter messages', () => {
|
||||
const result = extractLidPnFromMessage(
|
||||
'123456789012345@newsletter',
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
const result = extractLidPnFromMessage('123456789012345@newsletter', undefined, undefined, undefined)
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
@@ -235,11 +220,7 @@ describe('extractLidPnFromMessage', () => {
|
||||
describe('extractLidPnFromConversation', () => {
|
||||
describe('LID chat with pnJid', () => {
|
||||
it('should extract mapping when chat ID is @lid format with pnJid', () => {
|
||||
const result = extractLidPnFromConversation(
|
||||
'123456789012345@lid',
|
||||
undefined,
|
||||
'5511999999999@s.whatsapp.net'
|
||||
)
|
||||
const result = extractLidPnFromConversation('123456789012345@lid', undefined, '5511999999999@s.whatsapp.net')
|
||||
|
||||
expect(result).toEqual({
|
||||
lid: '123456789012345@lid',
|
||||
@@ -248,11 +229,7 @@ describe('extractLidPnFromConversation', () => {
|
||||
})
|
||||
|
||||
it('should extract mapping when chat ID is @hosted.lid format with pnJid', () => {
|
||||
const result = extractLidPnFromConversation(
|
||||
'123456789012345@hosted.lid',
|
||||
undefined,
|
||||
'5511999999999@hosted'
|
||||
)
|
||||
const result = extractLidPnFromConversation('123456789012345@hosted.lid', undefined, '5511999999999@hosted')
|
||||
|
||||
expect(result).toEqual({
|
||||
lid: '123456789012345@hosted.lid',
|
||||
@@ -263,11 +240,7 @@ describe('extractLidPnFromConversation', () => {
|
||||
|
||||
describe('PN chat with lidJid', () => {
|
||||
it('should extract mapping when chat ID is @s.whatsapp.net format with lidJid', () => {
|
||||
const result = extractLidPnFromConversation(
|
||||
'5511999999999@s.whatsapp.net',
|
||||
'123456789012345@lid',
|
||||
undefined
|
||||
)
|
||||
const result = extractLidPnFromConversation('5511999999999@s.whatsapp.net', '123456789012345@lid', undefined)
|
||||
|
||||
expect(result).toEqual({
|
||||
lid: '123456789012345@lid',
|
||||
@@ -276,11 +249,7 @@ describe('extractLidPnFromConversation', () => {
|
||||
})
|
||||
|
||||
it('should extract mapping when chat ID is @hosted format with lidJid', () => {
|
||||
const result = extractLidPnFromConversation(
|
||||
'5511999999999@hosted',
|
||||
'123456789012345@hosted.lid',
|
||||
undefined
|
||||
)
|
||||
const result = extractLidPnFromConversation('5511999999999@hosted', '123456789012345@hosted.lid', undefined)
|
||||
|
||||
expect(result).toEqual({
|
||||
lid: '123456789012345@hosted.lid',
|
||||
@@ -291,11 +260,7 @@ describe('extractLidPnFromConversation', () => {
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('should return undefined for group chats', () => {
|
||||
const result = extractLidPnFromConversation(
|
||||
'123456789012345@g.us',
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
const result = extractLidPnFromConversation('123456789012345@g.us', undefined, undefined)
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
@@ -311,41 +276,25 @@ describe('extractLidPnFromConversation', () => {
|
||||
})
|
||||
|
||||
it('should return undefined for broadcast lists (@broadcast)', () => {
|
||||
const result = extractLidPnFromConversation(
|
||||
'status@broadcast',
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
const result = extractLidPnFromConversation('status@broadcast', undefined, undefined)
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should return undefined when no alternate JID is available', () => {
|
||||
const result = extractLidPnFromConversation(
|
||||
'123456789012345@lid',
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
const result = extractLidPnFromConversation('123456789012345@lid', undefined, undefined)
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should return undefined when both lidJid and pnJid are null', () => {
|
||||
const result = extractLidPnFromConversation(
|
||||
'5511999999999@s.whatsapp.net',
|
||||
null,
|
||||
null
|
||||
)
|
||||
const result = extractLidPnFromConversation('5511999999999@s.whatsapp.net', null, null)
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should return undefined for LID chat with lidJid (no pnJid)', () => {
|
||||
const result = extractLidPnFromConversation(
|
||||
'123456789012345@lid',
|
||||
'987654321098765@lid',
|
||||
undefined
|
||||
)
|
||||
const result = extractLidPnFromConversation('123456789012345@lid', '987654321098765@lid', undefined)
|
||||
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
@@ -507,9 +456,7 @@ describe('processHistoryMessage', () => {
|
||||
|
||||
const result = processHistoryMessage(historySync)
|
||||
|
||||
expect(result.lidPnMappings).toEqual([
|
||||
{ lid: '11111111111111@lid', pn: '5511999999999@s.whatsapp.net' }
|
||||
])
|
||||
expect(result.lidPnMappings).toEqual([{ lid: '11111111111111@lid', pn: '5511999999999@s.whatsapp.net' }])
|
||||
})
|
||||
|
||||
it('should extract LID-PN mapping when chat ID is PN with lidJid', () => {
|
||||
@@ -526,17 +473,13 @@ describe('processHistoryMessage', () => {
|
||||
|
||||
const result = processHistoryMessage(historySync)
|
||||
|
||||
expect(result.lidPnMappings).toEqual([
|
||||
{ lid: '11111111111111@lid', pn: '5511999999999@s.whatsapp.net' }
|
||||
])
|
||||
expect(result.lidPnMappings).toEqual([{ lid: '11111111111111@lid', pn: '5511999999999@s.whatsapp.net' }])
|
||||
})
|
||||
|
||||
it('should deduplicate mappings from both sources', () => {
|
||||
const historySync: proto.IHistorySync = {
|
||||
syncType: proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP,
|
||||
phoneNumberToLidMappings: [
|
||||
{ lidJid: '11111111111111@lid', pnJid: '5511999999999@s.whatsapp.net' }
|
||||
],
|
||||
phoneNumberToLidMappings: [{ lidJid: '11111111111111@lid', pnJid: '5511999999999@s.whatsapp.net' }],
|
||||
conversations: [
|
||||
{
|
||||
id: '11111111111111@lid',
|
||||
@@ -558,9 +501,7 @@ describe('processHistoryMessage', () => {
|
||||
it('should combine mappings from both sources', () => {
|
||||
const historySync: proto.IHistorySync = {
|
||||
syncType: proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP,
|
||||
phoneNumberToLidMappings: [
|
||||
{ lidJid: '11111111111111@lid', pnJid: '5511999999999@s.whatsapp.net' }
|
||||
],
|
||||
phoneNumberToLidMappings: [{ lidJid: '11111111111111@lid', pnJid: '5511999999999@s.whatsapp.net' }],
|
||||
conversations: [
|
||||
{
|
||||
id: '22222222222222@lid',
|
||||
@@ -613,9 +554,7 @@ describe('processHistoryMessage', () => {
|
||||
|
||||
const result = processHistoryMessage(historySync)
|
||||
|
||||
expect(result.lidPnMappings).toEqual([
|
||||
{ lid: '11111111111111@hosted.lid', pn: '5511999999999@hosted' }
|
||||
])
|
||||
expect(result.lidPnMappings).toEqual([{ lid: '11111111111111@hosted.lid', pn: '5511999999999@hosted' }])
|
||||
})
|
||||
|
||||
it('should extract mappings for all conversation sync types', () => {
|
||||
@@ -639,28 +578,20 @@ describe('processHistoryMessage', () => {
|
||||
|
||||
const result = processHistoryMessage(historySync)
|
||||
|
||||
expect(result.lidPnMappings).toEqual([
|
||||
{ lid: '11111111111111@lid', pn: '5511999999999@s.whatsapp.net' }
|
||||
])
|
||||
expect(result.lidPnMappings).toEqual([{ lid: '11111111111111@lid', pn: '5511999999999@s.whatsapp.net' }])
|
||||
}
|
||||
})
|
||||
|
||||
it('should not extract conversation mappings for PUSH_NAME sync type', () => {
|
||||
const historySync: proto.IHistorySync = {
|
||||
syncType: proto.HistorySync.HistorySyncType.PUSH_NAME,
|
||||
pushnames: [
|
||||
{ id: '5511999999999@s.whatsapp.net', pushname: 'User Name' }
|
||||
],
|
||||
phoneNumberToLidMappings: [
|
||||
{ lidJid: '11111111111111@lid', pnJid: '5511999999999@s.whatsapp.net' }
|
||||
]
|
||||
pushnames: [{ id: '5511999999999@s.whatsapp.net', pushname: 'User Name' }],
|
||||
phoneNumberToLidMappings: [{ lidJid: '11111111111111@lid', pnJid: '5511999999999@s.whatsapp.net' }]
|
||||
}
|
||||
|
||||
const result = processHistoryMessage(historySync)
|
||||
|
||||
expect(result.lidPnMappings).toEqual([
|
||||
{ lid: '11111111111111@lid', pn: '5511999999999@s.whatsapp.net' }
|
||||
])
|
||||
expect(result.lidPnMappings).toEqual([{ lid: '11111111111111@lid', pn: '5511999999999@s.whatsapp.net' }])
|
||||
})
|
||||
|
||||
it('should not extract mapping from newsletter conversations', () => {
|
||||
@@ -765,9 +696,7 @@ describe('processHistoryMessage', () => {
|
||||
it('should deduplicate mappings from all three sources', () => {
|
||||
const historySync = {
|
||||
syncType: proto.HistorySync.HistorySyncType.INITIAL_BOOTSTRAP,
|
||||
phoneNumberToLidMappings: [
|
||||
{ lidJid: '11111111111111@lid', pnJid: '5511999999999@s.whatsapp.net' }
|
||||
],
|
||||
phoneNumberToLidMappings: [{ lidJid: '11111111111111@lid', pnJid: '5511999999999@s.whatsapp.net' }],
|
||||
conversations: [
|
||||
{
|
||||
id: '11111111111111@lid',
|
||||
|
||||
@@ -158,10 +158,12 @@ describe('processSyncAction', () => {
|
||||
phoneNumber: '5511999@s.whatsapp.net'
|
||||
}
|
||||
])
|
||||
expect(ev.emit).toHaveBeenCalledWith('lid-mapping.update', [{
|
||||
lid: '123@lid',
|
||||
pn: '5511999@s.whatsapp.net'
|
||||
}])
|
||||
expect(ev.emit).toHaveBeenCalledWith('lid-mapping.update', [
|
||||
{
|
||||
lid: '123@lid',
|
||||
pn: '5511999@s.whatsapp.net'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('does not emit events when id is missing', () => {
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
* Testes unitários para retry-utils.ts
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, jest } from '@jest/globals'
|
||||
import { beforeEach, describe, expect, it, jest } from '@jest/globals'
|
||||
import {
|
||||
retry,
|
||||
retryWithResult,
|
||||
createRetrier,
|
||||
retryable,
|
||||
RetryManager,
|
||||
RetryExhaustedError,
|
||||
RetryAbortedError,
|
||||
calculateDelay,
|
||||
retryPredicates,
|
||||
retryConfigs,
|
||||
getRetryDelayWithJitter,
|
||||
createRetrier,
|
||||
getAllRetryDelaysWithJitter,
|
||||
getRetryDelayWithJitter,
|
||||
retry,
|
||||
RETRY_BACKOFF_DELAYS,
|
||||
RETRY_JITTER_FACTOR,
|
||||
retryable,
|
||||
RetryAbortedError,
|
||||
retryConfigs,
|
||||
type RetryContext,
|
||||
RetryExhaustedError,
|
||||
RetryManager,
|
||||
retryPredicates,
|
||||
retryWithResult
|
||||
} from '../../Utils/retry-utils.js'
|
||||
|
||||
describe('retry', () => {
|
||||
@@ -29,10 +29,13 @@ describe('retry', () => {
|
||||
})
|
||||
|
||||
it('should return result from async operation', async () => {
|
||||
const result = await retry(async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
return 'async success'
|
||||
}, { collectMetrics: false })
|
||||
const result = await retry(
|
||||
async () => {
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
return 'async success'
|
||||
},
|
||||
{ collectMetrics: false }
|
||||
)
|
||||
|
||||
expect(result).toBe('async success')
|
||||
})
|
||||
@@ -48,12 +51,13 @@ describe('retry', () => {
|
||||
if (attempts < 3) {
|
||||
throw new Error('Failing')
|
||||
}
|
||||
|
||||
return 'success after retries'
|
||||
},
|
||||
{
|
||||
maxAttempts: 5,
|
||||
baseDelay: 10,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
}
|
||||
)
|
||||
|
||||
@@ -70,7 +74,7 @@ describe('retry', () => {
|
||||
{
|
||||
maxAttempts: 3,
|
||||
baseDelay: 10,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
}
|
||||
)
|
||||
).rejects.toThrow(RetryExhaustedError)
|
||||
@@ -80,7 +84,7 @@ describe('retry', () => {
|
||||
let receivedContext: RetryContext | null = null
|
||||
|
||||
await retry(
|
||||
(context) => {
|
||||
context => {
|
||||
receivedContext = context
|
||||
return 'success'
|
||||
},
|
||||
@@ -107,7 +111,7 @@ describe('retry', () => {
|
||||
maxAttempts: 5,
|
||||
baseDelay: 10,
|
||||
shouldRetry: () => false,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
}
|
||||
)
|
||||
).rejects.toThrow(RetryExhaustedError)
|
||||
@@ -127,13 +131,14 @@ describe('retry', () => {
|
||||
if (attempts < 3) {
|
||||
throw new Error('Failing')
|
||||
}
|
||||
|
||||
return 'success'
|
||||
},
|
||||
{
|
||||
maxAttempts: 5,
|
||||
baseDelay: 10,
|
||||
onRetry,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
}
|
||||
)
|
||||
|
||||
@@ -145,7 +150,7 @@ describe('retry', () => {
|
||||
|
||||
await retry(() => 'result', {
|
||||
onSuccess,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
|
||||
expect(onSuccess).toHaveBeenCalledWith('result', 1)
|
||||
@@ -163,7 +168,7 @@ describe('retry', () => {
|
||||
maxAttempts: 2,
|
||||
baseDelay: 10,
|
||||
onFailure,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
}
|
||||
)
|
||||
).rejects.toThrow()
|
||||
@@ -178,14 +183,14 @@ describe('retry', () => {
|
||||
|
||||
const promise = retry(
|
||||
async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||
await new Promise(resolve => setTimeout(resolve, 100))
|
||||
return 'success'
|
||||
},
|
||||
{
|
||||
maxAttempts: 5,
|
||||
baseDelay: 50,
|
||||
abortSignal: controller.signal,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
}
|
||||
)
|
||||
|
||||
@@ -214,7 +219,7 @@ describe('retryWithResult', () => {
|
||||
{
|
||||
maxAttempts: 2,
|
||||
baseDelay: 10,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
}
|
||||
)
|
||||
|
||||
@@ -287,7 +292,7 @@ describe('createRetrier', () => {
|
||||
const myRetrier = createRetrier({
|
||||
maxAttempts: 5,
|
||||
baseDelay: 10,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
})
|
||||
|
||||
let attempts = 0
|
||||
@@ -315,7 +320,7 @@ describe('retryable', () => {
|
||||
{
|
||||
maxAttempts: 5,
|
||||
baseDelay: 10,
|
||||
collectMetrics: false,
|
||||
collectMetrics: false
|
||||
}
|
||||
)
|
||||
|
||||
@@ -340,7 +345,7 @@ describe('RetryManager', () => {
|
||||
|
||||
it('should cancel active retry', async () => {
|
||||
const promise = manager.execute('cancelable', async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
return 'result'
|
||||
})
|
||||
|
||||
@@ -351,10 +356,12 @@ describe('RetryManager', () => {
|
||||
|
||||
it('should check if operation is active', async () => {
|
||||
let resolve: () => void
|
||||
const promise = manager.execute('active', () =>
|
||||
new Promise<string>((r) => {
|
||||
resolve = () => r('done')
|
||||
})
|
||||
const promise = manager.execute(
|
||||
'active',
|
||||
() =>
|
||||
new Promise<string>(r => {
|
||||
resolve = () => r('done')
|
||||
})
|
||||
)
|
||||
|
||||
expect(manager.isActive('active')).toBe(true)
|
||||
@@ -368,7 +375,7 @@ describe('RetryManager', () => {
|
||||
it('should cancel all operations', async () => {
|
||||
const promises = [
|
||||
manager.execute('op1', () => new Promise((_, reject) => setTimeout(() => reject(new Error()), 1000))),
|
||||
manager.execute('op2', () => new Promise((_, reject) => setTimeout(() => reject(new Error()), 1000))),
|
||||
manager.execute('op2', () => new Promise((_, reject) => setTimeout(() => reject(new Error()), 1000)))
|
||||
]
|
||||
|
||||
setTimeout(() => manager.cancelAll(), 20)
|
||||
@@ -425,8 +432,8 @@ describe('retryPredicates', () => {
|
||||
describe('or', () => {
|
||||
it('should combine predicates with OR', () => {
|
||||
const combined = retryPredicates.or(
|
||||
(e) => e.message.includes('A'),
|
||||
(e) => e.message.includes('B')
|
||||
e => e.message.includes('A'),
|
||||
e => e.message.includes('B')
|
||||
)
|
||||
|
||||
expect(combined(new Error('A'), 1)).toBe(true)
|
||||
@@ -438,8 +445,8 @@ describe('retryPredicates', () => {
|
||||
describe('and', () => {
|
||||
it('should combine predicates with AND', () => {
|
||||
const combined = retryPredicates.and(
|
||||
(e) => e.message.includes('A'),
|
||||
(e) => e.message.includes('B')
|
||||
e => e.message.includes('A'),
|
||||
e => e.message.includes('B')
|
||||
)
|
||||
|
||||
expect(combined(new Error('A and B'), 1)).toBe(true)
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
* Testes unitários para structured-logger.ts
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals'
|
||||
import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals'
|
||||
import {
|
||||
StructuredLogger,
|
||||
createStructuredLogger,
|
||||
getDefaultLogger,
|
||||
setDefaultLogger,
|
||||
createTimer,
|
||||
getDefaultLogger,
|
||||
LOG_LEVEL_VALUES,
|
||||
type LogLevel,
|
||||
setDefaultLogger,
|
||||
StructuredLogger
|
||||
} from '../../Utils/structured-logger.js'
|
||||
|
||||
describe('StructuredLogger', () => {
|
||||
@@ -21,7 +21,7 @@ describe('StructuredLogger', () => {
|
||||
logger = createStructuredLogger({
|
||||
level: 'debug',
|
||||
name: 'test',
|
||||
jsonFormat: false,
|
||||
jsonFormat: false
|
||||
})
|
||||
consoleSpy = jest.spyOn(console, 'info').mockImplementation(() => {})
|
||||
jest.spyOn(console, 'debug').mockImplementation(() => {})
|
||||
@@ -95,14 +95,14 @@ describe('StructuredLogger', () => {
|
||||
it('should redact sensitive fields', () => {
|
||||
const jsonLogger = createStructuredLogger({
|
||||
level: 'info',
|
||||
jsonFormat: true,
|
||||
jsonFormat: true
|
||||
})
|
||||
|
||||
// O logger deve sanitizar campos sensíveis
|
||||
jsonLogger.info({
|
||||
user: 'test',
|
||||
password: 'secret123',
|
||||
token: 'abc123',
|
||||
token: 'abc123'
|
||||
})
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalled()
|
||||
@@ -167,7 +167,7 @@ describe('StructuredLogger', () => {
|
||||
it('should measure elapsed time', async () => {
|
||||
const timer = createTimer()
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
|
||||
const elapsed = timer.elapsed()
|
||||
expect(elapsed).toBeGreaterThan(0)
|
||||
@@ -176,7 +176,7 @@ describe('StructuredLogger', () => {
|
||||
it('should format elapsed time', async () => {
|
||||
const timer = createTimer()
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 5))
|
||||
await new Promise(resolve => setTimeout(resolve, 5))
|
||||
|
||||
const formatted = timer.elapsedMs()
|
||||
expect(formatted).toMatch(/\d+\.\d+ms/)
|
||||
|
||||
@@ -2,36 +2,36 @@
|
||||
* Testes unitários para trace-context.ts
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach } from '@jest/globals'
|
||||
import { beforeEach, describe, expect, it } from '@jest/globals'
|
||||
import {
|
||||
addSpanEvent,
|
||||
createPrecisionTimer,
|
||||
createSpan,
|
||||
createTraceContext,
|
||||
endSpan,
|
||||
exportContext,
|
||||
extractTraceHeaders,
|
||||
generateCorrelationId,
|
||||
generateSpanId,
|
||||
generateTraceId,
|
||||
getAllBaggage,
|
||||
getBaggage,
|
||||
getCurrentContext,
|
||||
getOrCreateContext,
|
||||
importContext,
|
||||
injectTraceHeaders,
|
||||
removeBaggage,
|
||||
runWithContext,
|
||||
runWithNewContext,
|
||||
createSpan,
|
||||
startSpan,
|
||||
endSpan,
|
||||
addSpanEvent,
|
||||
setBaggage,
|
||||
setSpanAttributes,
|
||||
setSpanError,
|
||||
withSpan,
|
||||
withSpanSync,
|
||||
setBaggage,
|
||||
getBaggage,
|
||||
getAllBaggage,
|
||||
removeBaggage,
|
||||
injectTraceHeaders,
|
||||
extractTraceHeaders,
|
||||
exportContext,
|
||||
importContext,
|
||||
createPrecisionTimer,
|
||||
generateTraceId,
|
||||
generateSpanId,
|
||||
generateCorrelationId,
|
||||
type Span,
|
||||
startSpan,
|
||||
TRACE_HEADERS,
|
||||
type TraceContext,
|
||||
type Span,
|
||||
withSpan,
|
||||
withSpanSync
|
||||
} from '../../Utils/trace-context.js'
|
||||
|
||||
describe('ID generation', () => {
|
||||
@@ -47,6 +47,7 @@ describe('ID generation', () => {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
ids.add(generateTraceId())
|
||||
}
|
||||
|
||||
expect(ids.size).toBe(100)
|
||||
})
|
||||
})
|
||||
@@ -85,7 +86,7 @@ describe('TraceContext', () => {
|
||||
correlationId: 'custom-corr-id',
|
||||
parentSpanId: 'parent-span',
|
||||
baggage: { key: 'value' },
|
||||
metadata: { env: 'test' },
|
||||
metadata: { env: 'test' }
|
||||
})
|
||||
|
||||
expect(context.traceIds.traceId).toBe('custom-trace-id')
|
||||
@@ -174,7 +175,7 @@ describe('Spans', () => {
|
||||
it('should include provided attributes', () => {
|
||||
const span = createSpan({
|
||||
name: 'test',
|
||||
attributes: { key: 'value', count: 42 },
|
||||
attributes: { key: 'value', count: 42 }
|
||||
})
|
||||
|
||||
expect(span.attributes).toEqual({ key: 'value', count: 42 })
|
||||
@@ -287,7 +288,7 @@ describe('Spans', () => {
|
||||
expect(span.status).toBe('error')
|
||||
expect(span.attributes.error).toBe(true)
|
||||
expect(span.attributes.errorMessage).toBe('Something went wrong')
|
||||
expect(span.events.some((e) => e.name === 'exception')).toBe(true)
|
||||
expect(span.events.some(e => e.name === 'exception')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -295,7 +296,7 @@ describe('Spans', () => {
|
||||
describe('withSpan helpers', () => {
|
||||
describe('withSpan', () => {
|
||||
it('should execute async operation within span', async () => {
|
||||
const result = await withSpan('async-op', async (span) => {
|
||||
const result = await withSpan('async-op', async span => {
|
||||
expect(span.name).toBe('async-op')
|
||||
return 'async-result'
|
||||
})
|
||||
@@ -314,7 +315,7 @@ describe('withSpan helpers', () => {
|
||||
|
||||
describe('withSpanSync', () => {
|
||||
it('should execute sync operation within span', () => {
|
||||
const result = withSpanSync('sync-op', (span) => {
|
||||
const result = withSpanSync('sync-op', span => {
|
||||
expect(span.name).toBe('sync-op')
|
||||
return 'sync-result'
|
||||
})
|
||||
@@ -364,7 +365,7 @@ describe('Header injection/extraction', () => {
|
||||
describe('injectTraceHeaders', () => {
|
||||
it('should inject trace headers', () => {
|
||||
const context = createTraceContext({
|
||||
baggage: { user: 'test' },
|
||||
baggage: { user: 'test' }
|
||||
})
|
||||
|
||||
const headers = runWithContext(context, () => {
|
||||
@@ -394,7 +395,7 @@ describe('Header injection/extraction', () => {
|
||||
[TRACE_HEADERS.TRACE_ID]: 'trace-123',
|
||||
[TRACE_HEADERS.PARENT_SPAN_ID]: 'parent-456',
|
||||
[TRACE_HEADERS.CORRELATION_ID]: 'corr-789',
|
||||
[TRACE_HEADERS.BAGGAGE]: 'key1=value1,key2=value2',
|
||||
[TRACE_HEADERS.BAGGAGE]: 'key1=value1,key2=value2'
|
||||
}
|
||||
|
||||
const options = extractTraceHeaders(headers)
|
||||
@@ -412,7 +413,7 @@ describe('Context serialization', () => {
|
||||
it('should serialize context to JSON string', () => {
|
||||
const context = createTraceContext({
|
||||
baggage: { key: 'value' },
|
||||
metadata: { env: 'test' },
|
||||
metadata: { env: 'test' }
|
||||
})
|
||||
|
||||
const exported = exportContext(context)
|
||||
@@ -430,10 +431,10 @@ describe('Context serialization', () => {
|
||||
traceIds: {
|
||||
traceId: 'trace-123',
|
||||
spanId: 'span-456',
|
||||
correlationId: 'corr-789',
|
||||
correlationId: 'corr-789'
|
||||
},
|
||||
baggage: { imported: 'value' },
|
||||
metadata: { source: 'external' },
|
||||
metadata: { source: 'external' }
|
||||
})
|
||||
|
||||
const options = importContext(serialized)
|
||||
@@ -455,7 +456,7 @@ describe('PrecisionTimer', () => {
|
||||
it('should measure elapsed time', async () => {
|
||||
const timer = createPrecisionTimer()
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 20))
|
||||
await new Promise(resolve => setTimeout(resolve, 20))
|
||||
|
||||
const elapsed = timer.elapsed()
|
||||
expect(elapsed).toBeGreaterThan(10)
|
||||
@@ -464,7 +465,7 @@ describe('PrecisionTimer', () => {
|
||||
it('should format elapsed time', async () => {
|
||||
const timer = createPrecisionTimer()
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 5))
|
||||
await new Promise(resolve => setTimeout(resolve, 5))
|
||||
|
||||
const formatted = timer.elapsedFormatted()
|
||||
expect(formatted).toMatch(/\d+(\.\d+)?(µs|ms|s)/)
|
||||
@@ -473,11 +474,11 @@ describe('PrecisionTimer', () => {
|
||||
it('should stop timer', async () => {
|
||||
const timer = createPrecisionTimer()
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
|
||||
const stopped = timer.stop()
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 20))
|
||||
await new Promise(resolve => setTimeout(resolve, 20))
|
||||
|
||||
const afterStop = timer.elapsed()
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
* official WhatsApp Web client telemetry behavior.
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals'
|
||||
import type { BinaryNode } from '../../WABinary/types.js'
|
||||
import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals'
|
||||
import {
|
||||
UnifiedSessionManager,
|
||||
createUnifiedSessionManager,
|
||||
extractServerTime,
|
||||
shouldEnableUnifiedSession,
|
||||
UnifiedSessionManager,
|
||||
type UnifiedSessionOptions
|
||||
} from '../../Utils/unified-session.js'
|
||||
import type { BinaryNode } from '../../WABinary/types.js'
|
||||
|
||||
// TimeMs constants for testing (matching unified-session.ts)
|
||||
const TimeMs = {
|
||||
@@ -21,7 +21,7 @@ const TimeMs = {
|
||||
Minute: 60_000,
|
||||
Hour: 3_600_000,
|
||||
Day: 86_400_000,
|
||||
Week: 604_800_000,
|
||||
Week: 604_800_000
|
||||
} as const
|
||||
|
||||
// Mock the prometheus metrics to avoid side effects
|
||||
@@ -203,7 +203,7 @@ describe('UnifiedSessionManager', () => {
|
||||
|
||||
expect(mockSendNode).toHaveBeenCalledTimes(1)
|
||||
|
||||
const sentNode = mockSendNode.mock.calls[0]?.[0] as BinaryNode | undefined
|
||||
const sentNode = mockSendNode.mock.calls[0]?.[0]
|
||||
expect(sentNode).toBeDefined()
|
||||
expect(sentNode!.tag).toBe('ib')
|
||||
expect(Array.isArray(sentNode!.content)).toBe(true)
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { describe, expect, it } from '@jest/globals'
|
||||
import { isAnyLidUser, isAnyPnUser, isHostedLidUser, isHostedPnUser, isLidUser, isPnUser } from '../../WABinary/jid-utils'
|
||||
import {
|
||||
isAnyLidUser,
|
||||
isAnyPnUser,
|
||||
isHostedLidUser,
|
||||
isHostedPnUser,
|
||||
isLidUser,
|
||||
isPnUser
|
||||
} from '../../WABinary/jid-utils'
|
||||
|
||||
describe('JID Utility Functions', () => {
|
||||
describe('isAnyLidUser', () => {
|
||||
|
||||
Reference in New Issue
Block a user