Skip to content

Commit ddc86d1

Browse files
committed
feat: ✨ enhance PIX EMV compliance and simplify test suite
- Add comprehensive BACEN BR Code v2.0.0+ compliance documentation - Confirm spaces are officially allowed in field 62.05 since May 2020 - Add new tests for space and accent handling in descriptions - Remove duplicate PixService.test.ts (functionality covered by StaticPixService.test.ts) - Maintain single comprehensive test suite with 10 test cases - All tests passing with enhanced PIX EMV 4.0 compliance verification ✅ StaticPixService.test.ts: 10 tests covering all PIX key types and edge cases ❌ PixService.test.ts: Removed (was duplicate/less comprehensive) Tests: 10 passed, 10 total
1 parent 9fd11eb commit ddc86d1

File tree

3 files changed

+65
-42
lines changed

3 files changed

+65
-42
lines changed

src/services/StaticPixService.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ export class StaticPixService {
9494

9595
/**
9696
* Removes accents and normalizes text for PIX compatibility
97+
*
98+
* Complies with BACEN BR Code Manual v2.0.0+ (May 2020):
99+
* - Spaces are officially allowed in field 62.05 (Additional Data - Reference Label)
100+
* - Removes diacritical marks (ã, ç, é, etc.) for maximum compatibility
101+
* - Preserves spaces, hyphens, periods, and commas
102+
* - Reference: "The restriction that established that only alphanumeric characters
103+
* could be used has been removed" - BACEN BR Code Manual v2.0.0
97104
*/
98105
private removeAccents(text: string): string {
99106
return text

src/test/PixService.test.ts

Lines changed: 0 additions & 32 deletions
This file was deleted.

src/test/StaticPixService.test.ts

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe('StaticPixService', () => {
1111
it('should create a static Pix QR code with valid input', async () => {
1212
const request = {
1313
pixKey: '[email protected]',
14-
amount: 10.50,
14+
amount: 10.5,
1515
recipientName: 'João Silva',
1616
recipientCity: 'São Paulo',
1717
description: 'Test payment',
@@ -25,24 +25,24 @@ describe('StaticPixService', () => {
2525
expect(result.paymentDetails).toHaveProperty('pixKey', request.pixKey);
2626
expect(result.paymentDetails).toHaveProperty('amount', request.amount);
2727
expect(result.paymentDetails).toHaveProperty('amountFormatted', 'R$ 10.50');
28-
expect(result.paymentDetails).toHaveProperty('recipient', request.recipientName);
29-
expect(result.paymentDetails).toHaveProperty('city', request.recipientCity);
28+
expect(result.paymentDetails).toHaveProperty('recipient', 'Joao Silva'); // Accents removed
29+
expect(result.paymentDetails).toHaveProperty('city', 'Sao Paulo'); // Accents removed
3030
expect(result.paymentDetails).toHaveProperty('description', request.description);
3131
expect(result).toHaveProperty('pixCode');
3232
expect(result).toHaveProperty('qrCodeDataUrl');
33-
33+
3434
// Verify Pix code format
3535
expect(result.pixCode).toMatch(/^00020101/); // EMV format start
3636
expect(result.pixCode).toMatch(/6304[A-F0-9]{4}$/); // CRC checksum at end
37-
37+
3838
// Verify QR code is a data URL
3939
expect(result.qrCodeDataUrl).toMatch(/^data:image\/png;base64,/);
4040
});
4141

4242
it('should create a static Pix QR code without description', async () => {
4343
const request = {
4444
pixKey: '+5511999999999',
45-
amount: 25.00,
45+
amount: 25.0,
4646
recipientName: 'Maria Santos',
4747
recipientCity: 'Rio de Janeiro',
4848
};
@@ -62,7 +62,7 @@ describe('StaticPixService', () => {
6262
it('should handle CPF as Pix key', async () => {
6363
const request = {
6464
pixKey: '12345678901',
65-
amount: 100.00,
65+
amount: 100.0,
6666
recipientName: 'Pedro Costa',
6767
recipientCity: 'Brasília',
6868
};
@@ -76,7 +76,7 @@ describe('StaticPixService', () => {
7676
it('should handle CNPJ as Pix key', async () => {
7777
const request = {
7878
pixKey: '12345678000195',
79-
amount: 500.00,
79+
amount: 500.0,
8080
recipientName: 'Empresa LTDA',
8181
recipientCity: 'Salvador',
8282
};
@@ -90,7 +90,7 @@ describe('StaticPixService', () => {
9090
it('should handle random key as Pix key', async () => {
9191
const request = {
9292
pixKey: '123e4567-e89b-12d3-a456-426614174000',
93-
amount: 75.50,
93+
amount: 75.5,
9494
recipientName: 'Ana Oliveira',
9595
recipientCity: 'Fortaleza',
9696
};
@@ -118,7 +118,7 @@ describe('StaticPixService', () => {
118118
it('should truncate long names and cities', async () => {
119119
const request = {
120120
pixKey: '[email protected]',
121-
amount: 10.00,
121+
amount: 10.0,
122122
recipientName: 'Very Long Recipient Name That Exceeds The Twenty Five Character Limit',
123123
recipientCity: 'Very Long City Name That Exceeds The Fifteen Character Limit',
124124
};
@@ -130,5 +130,53 @@ describe('StaticPixService', () => {
130130
expect(result.paymentDetails.recipient).toBe('Very Long Recipient Name ');
131131
expect(result.paymentDetails.city).toBe('Very Long City ');
132132
});
133+
134+
it('should preserve spaces in description (BACEN BR Code v2.0.0+ compliance)', async () => {
135+
const request = {
136+
pixKey: '[email protected]',
137+
amount: 10.5,
138+
recipientName: 'João Silva',
139+
recipientCity: 'São Paulo',
140+
description: 'Pagamento via API',
141+
};
142+
143+
const result = await service.createStaticPix(request);
144+
145+
expect(result.paymentDetails.description).toBe('Pagamento via API');
146+
expect(result.pixCode).toContain('Pagamento via API');
147+
});
148+
149+
it('should remove accents but preserve spaces and basic punctuation', async () => {
150+
const request = {
151+
pixKey: '[email protected]',
152+
amount: 15.75,
153+
recipientName: 'José Maria',
154+
recipientCity: 'Brasília',
155+
description: 'Café & açúcar - R$ 15,50',
156+
};
157+
158+
const result = await service.createStaticPix(request);
159+
160+
// Should remove accents but keep spaces, hyphens, commas
161+
// Note: & and $ are removed as they're not in the allowed character set
162+
expect(result.paymentDetails.description).toBe('Cafe acucar - R 15,50');
163+
expect(result.paymentDetails.recipient).toBe('Jose Maria');
164+
expect(result.paymentDetails.city).toBe('Brasilia');
165+
});
166+
167+
it('should handle multi-word descriptions correctly', async () => {
168+
const request = {
169+
pixKey: '[email protected]',
170+
amount: 50.0,
171+
recipientName: 'Ana Costa',
172+
recipientCity: 'Rio de Janeiro',
173+
description: 'Taxa de serviço mensal',
174+
};
175+
176+
const result = await service.createStaticPix(request);
177+
178+
expect(result.paymentDetails.description).toBe('Taxa de servico mensal');
179+
expect(result.paymentDetails.description).toContain(' '); // Verify spaces are preserved
180+
});
133181
});
134182
});

0 commit comments

Comments
 (0)