Skip to content

Commit 5ee583e

Browse files
refactor: apply code review suggestions for passport module
1 parent 9b4c8b2 commit 5ee583e

10 files changed

Lines changed: 44 additions & 48 deletions

File tree

docs/pt-br/utilities.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,6 @@ import { formatPassport } from '@brazilian-utils/brazilian-utils';
454454

455455
formatPassport('ab123456'); // 'AB123456'
456456
formatPassport('AB-123.456'); // 'AB123456'
457-
formatPassport('12345678'); // null
458457
```
459458

460459
## generatePassport

docs/utilities.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,6 @@ import { formatPassport } from '@brazilian-utils/brazilian-utils';
454454

455455
formatPassport('ab123456'); // 'AB123456'
456456
formatPassport('AB-123.456'); // 'AB123456'
457-
formatPassport('12345678'); // null
458457
```
459458

460459
## generatePassport
Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
1-
import { beforeEach, describe, expect, test, vi } from "vitest";
2-
import { isValidPassport } from "../is-valid-passport/is-valid-passport";
1+
import { describe, expect, test } from "vitest";
32
import { formatPassport } from "./format-passport";
43

54
describe("formatPassport", () => {
6-
beforeEach(() => {
7-
vi.restoreAllMocks();
8-
});
5+
describe("should return the formatted passport", () => {
6+
test("when passport is valid", () => {
7+
expect(formatPassport("AB123456")).toBe("AB123456");
8+
});
99

10-
describe("should return the formatted passport", () => {
11-
test("when passport is valid", () => {
12-
vi.spyOn({ isValidPassport }, "isValidPassport").mockReturnValue(true);
13-
expect(formatPassport("yz 987654")).toBe("YZ987654");
14-
});
15-
});
16-
17-
describe("should return null", () => {
18-
test("when passport is not valid", () => {
19-
vi.spyOn({ isValidPassport }, "isValidPassport").mockReturnValue(false);
20-
expect(formatPassport("acd12736")).toBeNull();
21-
});
22-
});
10+
test("when passport has lowercase letters", () => {
11+
expect(formatPassport("acd12736")).toBe("ACD12736");
12+
});
13+
});
2314
});
Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
1-
import { isValidPassport } from "../is-valid-passport/is-valid-passport";
2-
import { parsePassport } from "../parse-passport/parse-passport";
3-
41
/**
52
* Formats a Brazilian passport number for display.
6-
* Returns the passport uppercased and without symbols, or null if invalid.
3+
* Converts to uppercase and removes all non-alphanumeric characters.
74
*
85
* @param passport - A Brazilian passport number (any case, possibly with symbols).
9-
* @returns The formatted passport number (uppercase, no symbols), or null if invalid.
6+
* @returns The formatted passport number (uppercase, no symbols), or an empty string if invalid.
107
*
118
* @example
12-
* formatPassport("Ab123456") // "AB123456"
13-
* formatPassport("Ab-123456") // "AB123456"
14-
* formatPassport("111111") // null
9+
* formatPassport("ab123456") // "AB123456"
10+
* formatPassport("AB-123.456") // "AB123456"
11+
* formatPassport("") // ""
1512
*/
16-
export const formatPassport = (passport: string): string | null => {
17-
const cleaned = parsePassport(passport.toUpperCase());
18-
return isValidPassport(cleaned) ? cleaned : null;
13+
export const formatPassport = (passport: string): string => {
14+
if (!passport || typeof passport !== "string") return "";
15+
return passport.toUpperCase().replace(/[^A-Z0-9]/g, "");
1916
};

src/generate-passport/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const LETTERS_LENGTH = 2;
2+
export const DIGITS_LENGTH = 6;
3+
export const ALPHABET_LENGTH = 26;
4+
export const CHAR_CODE_A = 65;

src/generate-passport/generate-passport.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { isValidPassport } from "../is-valid-passport/is-valid-passport";
33
import { generatePassport } from "./generate-passport";
44

55
describe("generatePassport", () => {
6-
test("should always generate a valid passport", () => {
7-
for (let i = 0; i < 10_000; i++) {
8-
expect(isValidPassport(generatePassport())).toBe(true);
9-
}
10-
});
6+
test("should always generate a valid passport", () => {
7+
for (let i = 0; i < 100; i++) {
8+
expect(isValidPassport(generatePassport())).toBe(true);
9+
}
10+
});
1111
});
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { generateRandomNumber } from "../_internals/generate-random-number/generate-random-number";
2+
import { LETTERS_LENGTH, DIGITS_LENGTH, ALPHABET_LENGTH, CHAR_CODE_A } from "./constants";
3+
14
/**
25
* Generates a random valid Brazilian passport number.
36
*
@@ -8,13 +11,11 @@
811
* generatePassport() // "ZS840088"
912
*/
1013
export const generatePassport = (): string => {
11-
const letters = Array.from({ length: 2 }, () =>
12-
String.fromCharCode(65 + Math.floor(Math.random() * 26)),
13-
).join("");
14+
const letters = Array.from({ length: LETTERS_LENGTH }, () =>
15+
String.fromCharCode(CHAR_CODE_A + Math.floor(Math.random() * ALPHABET_LENGTH)),
16+
).join("");
1417

15-
const digits = Array.from({ length: 6 }, () =>
16-
Math.floor(Math.random() * 10),
17-
).join("");
18+
const digits = generateRandomNumber(DIGITS_LENGTH);
1819

19-
return `${letters}${digits}`;
20+
return `${letters}${digits}`;
2021
};

src/is-valid-passport/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const PASSPORT_REGEX = /^[A-Z]{2}[0-9]{6}$/;

src/is-valid-passport/is-valid-passport.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { PASSPORT_REGEX } from "./constants";
2+
13
/**
24
* Checks if a Brazilian passport number is valid.
35
* To be considered valid, the input must be a string containing exactly two
@@ -14,7 +16,7 @@
1416
* isValidPassport("12345678") // false
1517
* isValidPassport("DC-221345") // false
1618
*/
17-
export const isValidPassport = (passport: string): boolean => {
18-
if (typeof passport !== "string") return false;
19-
return /^[A-Z]{2}[0-9]{6}$/.test(passport);
19+
export const isValidPassport = (passport: string | number): boolean => {
20+
if (passport === null || passport === undefined) return false;
21+
return PASSPORT_REGEX.test(String(passport));
2022
};

src/parse-passport/parse-passport.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@
99
* parsePassport("Ab-123456") // "Ab123456"
1010
* parsePassport("Ab -. 123456") // "Ab123456"
1111
*/
12-
export const parsePassport = (passport: string): string =>
13-
passport.replace(/[\s.-]/g, "");
12+
export const parsePassport = (passport: string): string => {
13+
if (!passport || typeof passport !== "string") return "";
14+
return passport.replace(/[^a-zA-Z0-9]/g, "");
15+
};

0 commit comments

Comments
 (0)