1import Foundation
2
3class PasswordGenerator {
4    func generate() -> String {
5        let uppercaseLetter = String(Unicode.Scalar(65 + Int(arc4random_uniform(26)))!)
6        let lowercaseLetter = String(Unicode.Scalar(97 + Int(arc4random_uniform(26)))!)
7        let digit = String(Int(arc4random_uniform(10)))
8        let specialCharacter = "!@#$%^&*()_+-=[]{}|;:'\",.<>?/`~"
9        let specialChar = String(specialCharacter[specialCharacter.index(specialCharacter.startIndex, offsetBy: Int(arc4random_uniform(UInt32(specialCharacter.count))))])
10
11        var password = uppercaseLetter + lowercaseLetter + digit + specialChar
12
13        while password.count < 8 {
14            let randomChar = String(Unicode.Scalar(33 + Int(arc4random_uniform(94)))!)
15            password += randomChar
16        }
17
18        return password
19    }
20}
21
22func test_password_has_at_least_eight_characters() {
23	let sut = PasswordGenerator()
24	let password = sut.generate()
25	if password.count < 8 {
26		fail("Password should have at least eight characters")
27	}
28}
29
30func test_password_contains_at_least_one_uppercase_letter() {
31	let sut = PasswordGenerator()
32	let password = sut.generate()
33	let uppercaseRange = password.rangeOfCharacter(from: .uppercaseLetters)
34	if uppercaseRange == nil {
35		fail("Password should contain at least one uppercase letter")
36	}
37}
38
39func test_password_contains_at_least_one_lowercase_letter() {
40	let sut = PasswordGenerator()
41	let password = sut.generate()
42	let lowercaseRange = password.rangeOfCharacter(from: .lowercaseLetters)
43	if lowercaseRange == nil {
44		fail("Password should contain at least one lowercase letter")
45	}
46}
47
48func test_password_contains_at_least_one_digit() {
49	let sut = PasswordGenerator()
50	let password = sut.generate()
51	let digitRange = password.rangeOfCharacter(from: .decimalDigits)
52	if digitRange == nil {
53		fail("Password should contain at least one digit")
54	}
55}
56
57func test_password_contains_at_least_one_special_character() {
58	let sut = PasswordGenerator()
59	let password = sut.generate()
60	let specialCharacters = CharacterSet(charactersIn: "!@#$%^&*()_+-=[]{}|;:'\",.<>?/`~")
61	let specialCharRange = password.rangeOfCharacter(from: specialCharacters)
62	if specialCharRange == nil {
63		fail("Password should contain at least one special character")
64	}
65}
66
67func test_password_does_not_contain_spaces() {
68	let sut = PasswordGenerator()
69	let password = sut.generate()
70	if password.contains(" ") {
71		fail("Password should not contain spaces")
72	}
73}
74
75func test_password_is_unique() {
76	let sut = PasswordGenerator()
77	let password1 = sut.generate()
78	let password2 = sut.generate()
79	if password1 == password2 {
80		fail("Generated passwords should be unique")
81	}
82}
83
84func test_password_meets_all_criteria() {
85	let sut = PasswordGenerator()
86	let password = sut.generate()
87	
88	Comprueba que la contraseña tiene al menos una letra mayúscula
89	let uppercaseRange = password.rangeOfCharacter(from: .uppercaseLetters)
90	if uppercaseRange == nil {
91		fail("Password should contain at least one uppercase letter")
92	}
93	
94	Comprueba que la contraseña tiene al menos una letra minúscula
95	let lowercaseRange = password.rangeOfCharacter(from: .lowercaseLetters)
96	if lowercaseRange == nil {
97		fail("Password should contain at least one lowercase letter")
98	}
99	
100	Comprueba que la contraseña tiene al menos un dígito
101	let digitRange = password.rangeOfCharacter(from: .decimalDigits)
102	if digitRange == nil {
103		fail("Password should contain at least one digit")
104	}
105	
106	Comprueba que la contraseña tiene al menos un carácter especial
107	let specialCharacters = CharacterSet(charactersIn: "!@#$%^&*()_+-=[]{}|;:'\",.<>?/`~")
108	let specialCharRange = password.rangeOfCharacter(from: specialCharacters)
109	if specialCharRange == nil {
110		fail("Password should contain at least one special character")
111	}
112	
113	Comprueba que la contraseña no contiene espacios
114	if password.contains(" ") {
115		fail("Password should not contain spaces")
116	}
117	
118	Comprueba que la longitud es al menos 8 caracteres
119	if password.count < 8 {
120		fail("Password should have at least eight characters")
121	}
122}
123
124test_password_has_at_least_eight_characters()
125test_password_contains_at_least_one_uppercase_letter()
126test_password_contains_at_least_one_lowercase_letter()
127test_password_contains_at_least_one_digit()
128test_password_contains_at_least_one_special_character()
129test_password_does_not_contain_spaces()
130test_password_is_unique()
131test_password_meets_all_criteria()
132
133Función auxiliar para imprimir el fallo
134func fail(_ description: String, function: String = #function) {
135	print("❌ — \(function), \(description)")
136}