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:
Claude
2026-02-13 21:59:35 +00:00
parent ce98b240ca
commit 4b02652369
63 changed files with 1677 additions and 1897 deletions
+23 -21
View File
@@ -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))
+36 -132
View File
@@ -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 -1
View File
@@ -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', () => {
+10 -10
View File
@@ -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'
})
+17 -19
View File
@@ -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
}
)
+1 -1
View File
@@ -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', () => {
+24 -95
View File
@@ -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', () => {
+44 -37
View File
@@ -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/)
+35 -34
View File
@@ -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 -5
View File
@@ -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)
+8 -1
View File
@@ -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', () => {