Skip to content

Commit 3330ae5

Browse files
committed
Add comprehensive HSL color tests
- Test HSL to RGB conversion accuracy for pure colors and grayscale - Test HSL parameter normalization (hue wrapping, saturation/lightness clamping) - Test String HSL methods for both foreground and background colors - Test HSL method chaining with other styles - Test HSL with disabled Rainbow functionality - Test 8-bit approximation vs 24-bit color modes - Test edge cases and boundary conditions
1 parent 2f692ff commit 3330ae5

1 file changed

Lines changed: 223 additions & 0 deletions

File tree

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
//
2+
// HSLColorTests.swift
3+
// Rainbow
4+
//
5+
// Created by Rainbow on 16/7/25.
6+
//
7+
8+
import XCTest
9+
@testable import Rainbow
10+
11+
class HSLColorTests: XCTestCase {
12+
13+
override func setUp() {
14+
super.setUp()
15+
Rainbow.outputTarget = .console
16+
Rainbow.enabled = true
17+
}
18+
19+
func testHSLToRGBConversion() {
20+
// Test pure colors
21+
let redConverter = HSLColorConverter(hue: 0, saturation: 100, lightness: 50)
22+
let redRGB = redConverter.toRGB()
23+
XCTAssertEqual(redRGB.0, 255)
24+
XCTAssertEqual(redRGB.1, 0)
25+
XCTAssertEqual(redRGB.2, 0)
26+
27+
let greenConverter = HSLColorConverter(hue: 120, saturation: 100, lightness: 50)
28+
let greenRGB = greenConverter.toRGB()
29+
XCTAssertEqual(greenRGB.0, 0)
30+
XCTAssertEqual(greenRGB.1, 255)
31+
XCTAssertEqual(greenRGB.2, 0)
32+
33+
let blueConverter = HSLColorConverter(hue: 240, saturation: 100, lightness: 50)
34+
let blueRGB = blueConverter.toRGB()
35+
XCTAssertEqual(blueRGB.0, 0)
36+
XCTAssertEqual(blueRGB.1, 0)
37+
XCTAssertEqual(blueRGB.2, 255)
38+
39+
// Test grayscale (saturation = 0)
40+
let grayConverter = HSLColorConverter(hue: 0, saturation: 0, lightness: 50)
41+
let grayRGB = grayConverter.toRGB()
42+
XCTAssertEqual(grayRGB.0, 128)
43+
XCTAssertEqual(grayRGB.1, 128)
44+
XCTAssertEqual(grayRGB.2, 128)
45+
46+
let blackConverter = HSLColorConverter(hue: 0, saturation: 0, lightness: 0)
47+
let blackRGB = blackConverter.toRGB()
48+
XCTAssertEqual(blackRGB.0, 0)
49+
XCTAssertEqual(blackRGB.1, 0)
50+
XCTAssertEqual(blackRGB.2, 0)
51+
52+
let whiteConverter = HSLColorConverter(hue: 0, saturation: 0, lightness: 100)
53+
let whiteRGB = whiteConverter.toRGB()
54+
XCTAssertEqual(whiteRGB.0, 255)
55+
XCTAssertEqual(whiteRGB.1, 255)
56+
XCTAssertEqual(whiteRGB.2, 255)
57+
58+
// Test intermediate colors
59+
let orangeConverter = HSLColorConverter(hue: 30, saturation: 100, lightness: 50)
60+
let orangeRGB = orangeConverter.toRGB()
61+
XCTAssertEqual(orangeRGB.0, 255)
62+
XCTAssertEqual(orangeRGB.1, 128)
63+
XCTAssertEqual(orangeRGB.2, 0)
64+
65+
let purpleConverter = HSLColorConverter(hue: 270, saturation: 50, lightness: 50)
66+
let purpleRGB = purpleConverter.toRGB()
67+
XCTAssertEqual(purpleRGB.0, 127)
68+
XCTAssertEqual(purpleRGB.1, 64)
69+
XCTAssertEqual(purpleRGB.2, 191)
70+
}
71+
72+
func testHSLNormalization() {
73+
// Test hue wrapping
74+
let converter1 = HSLColorConverter(hue: 380, saturation: 100, lightness: 50)
75+
let converter2 = HSLColorConverter(hue: 20, saturation: 100, lightness: 50)
76+
let rgb1 = converter1.toRGB()
77+
let rgb2 = converter2.toRGB()
78+
XCTAssertEqual(rgb1.0, rgb2.0)
79+
XCTAssertEqual(rgb1.1, rgb2.1)
80+
XCTAssertEqual(rgb1.2, rgb2.2)
81+
82+
let converter3 = HSLColorConverter(hue: -20, saturation: 100, lightness: 50)
83+
let converter4 = HSLColorConverter(hue: 340, saturation: 100, lightness: 50)
84+
let rgb3 = converter3.toRGB()
85+
let rgb4 = converter4.toRGB()
86+
XCTAssertEqual(rgb3.0, rgb4.0)
87+
XCTAssertEqual(rgb3.1, rgb4.1)
88+
XCTAssertEqual(rgb3.2, rgb4.2)
89+
90+
// Test saturation clamping
91+
let converter5 = HSLColorConverter(hue: 0, saturation: 150, lightness: 50)
92+
let converter6 = HSLColorConverter(hue: 0, saturation: 100, lightness: 50)
93+
let rgb5 = converter5.toRGB()
94+
let rgb6 = converter6.toRGB()
95+
XCTAssertEqual(rgb5.0, rgb6.0)
96+
XCTAssertEqual(rgb5.1, rgb6.1)
97+
XCTAssertEqual(rgb5.2, rgb6.2)
98+
99+
let converter7 = HSLColorConverter(hue: 0, saturation: -50, lightness: 50)
100+
let converter8 = HSLColorConverter(hue: 0, saturation: 0, lightness: 50)
101+
let rgb7 = converter7.toRGB()
102+
let rgb8 = converter8.toRGB()
103+
XCTAssertEqual(rgb7.0, rgb8.0)
104+
XCTAssertEqual(rgb7.1, rgb8.1)
105+
XCTAssertEqual(rgb7.2, rgb8.2)
106+
107+
// Test lightness clamping
108+
let converter9 = HSLColorConverter(hue: 0, saturation: 100, lightness: 150)
109+
let converter10 = HSLColorConverter(hue: 0, saturation: 100, lightness: 100)
110+
let rgb9 = converter9.toRGB()
111+
let rgb10 = converter10.toRGB()
112+
XCTAssertEqual(rgb9.0, rgb10.0)
113+
XCTAssertEqual(rgb9.1, rgb10.1)
114+
XCTAssertEqual(rgb9.2, rgb10.2)
115+
}
116+
117+
func testStringHSLMethods() {
118+
// Test foreground HSL
119+
let text = "Hello"
120+
121+
// Pure red
122+
let redText = text.hsl(0, 100, 50, to: .bit24)
123+
XCTAssertTrue(redText.contains("\u{001B}[38;2;255;0;0m"))
124+
125+
// Pure green
126+
let greenText = text.hsl(120, 100, 50, to: .bit24)
127+
XCTAssertTrue(greenText.contains("\u{001B}[38;2;0;255;0m"))
128+
129+
// Gray
130+
let grayText = text.hsl(0, 0, 50, to: .bit24)
131+
XCTAssertTrue(grayText.contains("\u{001B}[38;2;128;128;128m"))
132+
133+
// Test with HSL tuple
134+
let hslColor: HSL = (hue: 240, saturation: 100, lightness: 50)
135+
let blueText = text.hsl(hslColor, to: .bit24)
136+
XCTAssertTrue(blueText.contains("\u{001B}[38;2;0;0;255m"))
137+
}
138+
139+
func testStringOnHSLMethods() {
140+
// Test background HSL
141+
let text = "Hello"
142+
143+
// Pure red background
144+
let redBgText = text.onHsl(0, 100, 50, to: .bit24)
145+
XCTAssertTrue(redBgText.contains("\u{001B}[48;2;255;0;0m"))
146+
147+
// Pure green background
148+
let greenBgText = text.onHsl(120, 100, 50, to: .bit24)
149+
XCTAssertTrue(greenBgText.contains("\u{001B}[48;2;0;255;0m"))
150+
151+
// Gray background
152+
let grayBgText = text.onHsl(0, 0, 50, to: .bit24)
153+
XCTAssertTrue(grayBgText.contains("\u{001B}[48;2;128;128;128m"))
154+
155+
// Test with HSL tuple
156+
let hslColor: HSL = (hue: 240, saturation: 100, lightness: 50)
157+
let blueBgText = text.onHsl(hslColor, to: .bit24)
158+
XCTAssertTrue(blueBgText.contains("\u{001B}[48;2;0;0;255m"))
159+
}
160+
161+
func testHSL8BitApproximation() {
162+
// Test that 8-bit approximation works
163+
let text = "Hello"
164+
165+
// This should use ColorApproximation to convert to 8-bit
166+
let redText = text.hsl(0, 100, 50) // default is .bit8Approximated
167+
// Should contain an 8-bit color code, not 24-bit
168+
XCTAssertFalse(redText.contains("38;2;"))
169+
XCTAssertTrue(redText.contains("\u{001B}["))
170+
171+
let bgText = text.onHsl(120, 100, 50)
172+
XCTAssertFalse(bgText.contains("48;2;"))
173+
XCTAssertTrue(bgText.contains("\u{001B}["))
174+
}
175+
176+
func testHSLChaining() {
177+
// Test that HSL methods can be chained with other methods
178+
let text = "Hello"
179+
180+
let styledText = text.hsl(180, 100, 50).bold.underline
181+
// Should contain escape sequences for color, bold, and underline
182+
XCTAssertTrue(styledText.contains("\u{001B}["))
183+
XCTAssertTrue(styledText.contains("1;")) // bold
184+
XCTAssertTrue(styledText.contains("4m")) // underline
185+
186+
let complexText = text.hsl(60, 100, 50).onHsl(300, 100, 50, to: .bit24).italic
187+
// Should contain escape sequences for foreground, background, and italic
188+
XCTAssertTrue(complexText.contains("\u{001B}["))
189+
XCTAssertTrue(complexText.contains("3m")) // italic
190+
XCTAssertTrue(complexText.contains("48;2;")) // 24-bit background color
191+
}
192+
193+
func testHSLWithDisabledRainbow() {
194+
Rainbow.enabled = false
195+
196+
let text = "Hello"
197+
let result = text.hsl(0, 100, 50)
198+
XCTAssertEqual(result, text)
199+
200+
let bgResult = text.onHsl(120, 100, 50)
201+
XCTAssertEqual(bgResult, text)
202+
203+
Rainbow.enabled = true
204+
}
205+
206+
func testHSLEdgeCases() {
207+
// Test various edge cases
208+
let text = "Test"
209+
210+
// Hue at boundaries
211+
let hue360 = text.hsl(360, 100, 50, to: .bit24)
212+
let hue0 = text.hsl(0, 100, 50, to: .bit24)
213+
XCTAssertEqual(hue360, hue0) // 360 degrees should equal 0 degrees
214+
215+
// Low saturation, high lightness (pastel colors)
216+
let pastel = text.hsl(180, 25, 80, to: .bit24)
217+
XCTAssertTrue(pastel.contains("\u{001B}[38;2;"))
218+
219+
// High saturation, low lightness (dark colors)
220+
let dark = text.hsl(60, 100, 20, to: .bit24)
221+
XCTAssertTrue(dark.contains("\u{001B}[38;2;"))
222+
}
223+
}

0 commit comments

Comments
 (0)