Skip to content

Commit 5b220d0

Browse files
committed
Enhance L33t matcher test coverage
Add comprehensive tests covering: - Early bailout when no l33t characters present - Multiple l33t substitution types - Ambiguous l33t characters (e.g., '1' for 'i' or 'l') - Mixed case password handling - Edge cases (empty passwords, repeated characters) - Detailed translate method testing - l33t flag and sub_display field verification Test count increased from 9 to 27 examples.
1 parent 006fceb commit 5b220d0

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

spec/matchers/l33t_spec.rb

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,107 @@
7373
]
7474
)
7575
end
76+
77+
it 'marks all matches as l33t' do
78+
expect(matches.map(&:l33t).uniq).to eq([true])
79+
end
80+
81+
it 'sets the sub_display field' do
82+
expect(matches.first.sub_display).to eq('@ -> a')
83+
end
84+
85+
context 'with no l33t characters' do
86+
it 'returns empty array for password without l33t chars' do
87+
expect(matcher.matches('password')).to be_empty
88+
end
89+
90+
it 'returns empty array for simple words' do
91+
expect(matcher.matches('hello')).to be_empty
92+
end
93+
end
94+
95+
context 'with multiple l33t substitutions' do
96+
it 'handles multiple substitution types' do
97+
matches = matcher.matches('p@ssw0rd')
98+
expect(matches).not_to be_empty
99+
expect(matches.any? { |m| m.sub.keys.include?('@') }).to be true
100+
expect(matches.any? { |m| m.sub.keys.include?('0') }).to be true
101+
end
102+
103+
it 'creates correct sub_display for multiple substitutions' do
104+
matches = matcher.matches('h3ll0')
105+
multi_sub_match = matches.find { |m| m.sub.length > 1 }
106+
expect(multi_sub_match.sub_display).to include('->')
107+
end
108+
end
109+
110+
context 'with same character representing different letters' do
111+
it 'handles ambiguous l33t characters' do
112+
# '1' can represent both 'i' and 'l'
113+
matches = matcher.matches('test1ng')
114+
expect(matches).not_to be_empty
115+
end
116+
end
117+
118+
context 'with uppercase l33t speak' do
119+
it 'finds matches in mixed case passwords' do
120+
matches = matcher.matches('P@ssW0RD')
121+
expect(matches).not_to be_empty
122+
end
123+
124+
it 'preserves original case in token' do
125+
matches = matcher.matches('P@SS')
126+
uppercase_match = matches.find { |m| m.token == 'P@S' }
127+
expect(uppercase_match).not_to be_nil
128+
expect(uppercase_match.token).to eq('P@S')
129+
expect(uppercase_match.matched_word).to eq('pas')
130+
end
131+
end
132+
133+
context 'with edge cases' do
134+
it 'handles empty password' do
135+
expect(matcher.matches('')).to be_empty
136+
end
137+
138+
it 'handles password with only l33t characters' do
139+
matches = matcher.matches('@$')
140+
expect(matches).to be_an(Array)
141+
end
142+
143+
it 'handles repeated l33t characters' do
144+
matches = matcher.matches('@@@@')
145+
expect(matches).to be_an(Array)
146+
end
147+
end
148+
end
149+
150+
describe '#translate' do
151+
it 'substitutes l33t characters with their letter equivalents' do
152+
substitution = { '@' => 'a', '0' => 'o' }
153+
expect(matcher.translate('p@ssw0rd', substitution)).to eq('password')
154+
end
155+
156+
it 'leaves non-substituted characters unchanged' do
157+
substitution = { '@' => 'a' }
158+
expect(matcher.translate('p@ssword', substitution)).to eq('password')
159+
end
160+
161+
it 'handles empty password' do
162+
expect(matcher.translate('', { '@' => 'a' })).to eq('')
163+
end
164+
165+
it 'handles empty substitution table' do
166+
expect(matcher.translate('password', {})).to eq('password')
167+
end
168+
169+
it 'handles multiple occurrences of same character' do
170+
substitution = { '@' => 'a' }
171+
expect(matcher.translate('@@@@', substitution)).to eq('aaaa')
172+
end
173+
174+
it 'only substitutes specified characters' do
175+
substitution = { '3' => 'e' }
176+
expect(matcher.translate('l33t', substitution)).to eq('leet')
177+
end
76178
end
77179
end

0 commit comments

Comments
 (0)