import { describe, it, expect } from 'vitest'; import { redactErrMsg } from './redact-error.js'; describe('redactErrMsg', () => { it('redacts user:password from a postgres:// URL embedded in an error message', () => { const msg = 'connect ECONNREFUSED postgres://admin:s3cr3t@db.example.com:5432/mosaic'; expect(redactErrMsg(msg)).toBe( 'connect ECONNREFUSED postgres://***@db.example.com:5432/mosaic', ); }); it('redacts user:password from a postgresql:// URL', () => { const msg = 'connection failed: postgresql://myuser:mypass@localhost:5432/testdb'; expect(redactErrMsg(msg)).toBe('connection failed: postgresql://***@localhost:5432/testdb'); }); it('handles URLs with no password (user only) — still redacts userinfo', () => { const msg = 'error postgres://justuser@host:5432/db'; expect(redactErrMsg(msg)).toBe('error postgres://***@host:5432/db'); }); it('returns the original message unchanged when no connection URL is present', () => { const msg = 'connection timed out after 5 seconds'; expect(redactErrMsg(msg)).toBe('connection timed out after 5 seconds'); }); it('is case-insensitive for the scheme (scheme is normalized to lowercase in output)', () => { // The regex replacement uses a lowercase literal, so the matched scheme is // replaced with the lowercase form regardless of the original casing. const msg = 'POSTGRES://admin:pass@host:5432/db'; expect(redactErrMsg(msg)).toBe('postgres://***@host:5432/db'); }); it('redacts multiple URLs in a single message', () => { const msg = 'src postgres://u:p@host1/db1 dst postgresql://v:q@host2/db2'; expect(redactErrMsg(msg)).toBe('src postgres://***@host1/db1 dst postgresql://***@host2/db2'); }); it('does not alter a message with a postgres URL that has no userinfo', () => { // No userinfo component — pattern does not match, message unchanged. const msg = 'error at postgres://host:5432/db'; expect(redactErrMsg(msg)).toBe('error at postgres://host:5432/db'); }); it('redacts user:password from a redis:// URL', () => { const msg = 'connect ECONNREFUSED redis://user:pass@host:6379'; expect(redactErrMsg(msg)).toBe('connect ECONNREFUSED redis://***@host:6379'); }); it('redacts user:password from a rediss:// URL (TLS)', () => { const msg = 'connect ECONNREFUSED rediss://user:pass@host:6379'; expect(redactErrMsg(msg)).toBe('connect ECONNREFUSED rediss://***@host:6379'); }); it('redacts both a postgres URL and a redis URL in the same message', () => { const msg = 'primary postgres://admin:s3cr3t@db:5432/mosaic cache redis://cacheuser:cachepass@cache:6379'; expect(redactErrMsg(msg)).toBe( 'primary postgres://***@db:5432/mosaic cache redis://***@cache:6379', ); }); });