Skip to content

Commit a491a9e

Browse files
authored
Merge pull request #8376 from Piyushrathoree/add-hsb-tests
add unit tests for HSB color space
2 parents daac93f + 8e16c6c commit a491a9e

1 file changed

Lines changed: 239 additions & 0 deletions

File tree

test/unit/color/hsb.js

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
/**
2+
* Tests for the HSB (Hue, Saturation, Brightness) color space.
3+
*
4+
* The HSB color space is defined in src/color/color_spaces/hsb.js and provides
5+
* conversions between RGB (base) and HSB color representations.
6+
*
7+
* HSB ranges:
8+
* - Hue: 0-360 (degrees on color wheel)
9+
* - Saturation: 0-100 (percentage)
10+
* - Brightness: 0-100 (percentage)
11+
*
12+
* RGB ranges (in colorjs.io):
13+
* - R, G, B: 0-1 (normalized)
14+
*/
15+
16+
import HSBSpace from '../../../src/color/color_spaces/hsb.js';
17+
18+
suite('color/HSB Color Space', function() {
19+
const accuracy = 0.01;
20+
21+
suite('HSB to RGB conversion (toBase)', function() {
22+
suite('Primary Colors', function() {
23+
test('pure red: HSB(0, 100, 100) → RGB(1, 0, 0)', function() {
24+
const result = HSBSpace.toBase([0, 100, 100]);
25+
assert.approximately(result[0], 1, accuracy);
26+
assert.approximately(result[1], 0, accuracy);
27+
assert.approximately(result[2], 0, accuracy);
28+
});
29+
30+
test('pure green: HSB(120, 100, 100) → RGB(0, 1, 0)', function() {
31+
const result = HSBSpace.toBase([120, 100, 100]);
32+
assert.approximately(result[0], 0, accuracy);
33+
assert.approximately(result[1], 1, accuracy);
34+
assert.approximately(result[2], 0, accuracy);
35+
});
36+
37+
test('pure blue: HSB(240, 100, 100) → RGB(0, 0, 1)', function() {
38+
const result = HSBSpace.toBase([240, 100, 100]);
39+
assert.approximately(result[0], 0, accuracy);
40+
assert.approximately(result[1], 0, accuracy);
41+
assert.approximately(result[2], 1, accuracy);
42+
});
43+
});
44+
45+
suite('Secondary Colors', function() {
46+
test('yellow: HSB(60, 100, 100) → RGB(1, 1, 0)', function() {
47+
const result = HSBSpace.toBase([60, 100, 100]);
48+
assert.approximately(result[0], 1, accuracy);
49+
assert.approximately(result[1], 1, accuracy);
50+
assert.approximately(result[2], 0, accuracy);
51+
});
52+
53+
test('cyan: HSB(180, 100, 100) → RGB(0, 1, 1)', function() {
54+
const result = HSBSpace.toBase([180, 100, 100]);
55+
assert.approximately(result[0], 0, accuracy);
56+
assert.approximately(result[1], 1, accuracy);
57+
assert.approximately(result[2], 1, accuracy);
58+
});
59+
60+
test('magenta: HSB(300, 100, 100) → RGB(1, 0, 1)', function() {
61+
const result = HSBSpace.toBase([300, 100, 100]);
62+
assert.approximately(result[0], 1, accuracy);
63+
assert.approximately(result[1], 0, accuracy);
64+
assert.approximately(result[2], 1, accuracy);
65+
});
66+
});
67+
68+
suite('Grayscale (Saturation = 0)', function() {
69+
test('white: HSB(0, 0, 100) → RGB(1, 1, 1)', function() {
70+
const result = HSBSpace.toBase([0, 0, 100]);
71+
assert.approximately(result[0], 1, accuracy);
72+
assert.approximately(result[1], 1, accuracy);
73+
assert.approximately(result[2], 1, accuracy);
74+
});
75+
76+
test('black: HSB(0, 0, 0) → RGB(0, 0, 0)', function() {
77+
const result = HSBSpace.toBase([0, 0, 0]);
78+
assert.approximately(result[0], 0, accuracy);
79+
assert.approximately(result[1], 0, accuracy);
80+
assert.approximately(result[2], 0, accuracy);
81+
});
82+
83+
test('mid gray: HSB(0, 0, 50) → RGB(0.5, 0.5, 0.5)', function() {
84+
const result = HSBSpace.toBase([0, 0, 50]);
85+
assert.approximately(result[0], 0.5, accuracy);
86+
assert.approximately(result[1], 0.5, accuracy);
87+
assert.approximately(result[2], 0.5, accuracy);
88+
});
89+
90+
test('grayscale ignores hue: HSB(180, 0, 50) → RGB(0.5, 0.5, 0.5)', function() {
91+
const result = HSBSpace.toBase([180, 0, 50]);
92+
assert.approximately(result[0], 0.5, accuracy);
93+
assert.approximately(result[1], 0.5, accuracy);
94+
assert.approximately(result[2], 0.5, accuracy);
95+
});
96+
});
97+
98+
suite('Partial Saturation', function() {
99+
test('50% saturation red: HSB(0, 50, 100) → RGB(1, 0.5, 0.5)', function() {
100+
const result = HSBSpace.toBase([0, 50, 100]);
101+
assert.approximately(result[0], 1, accuracy);
102+
assert.approximately(result[1], 0.5, accuracy);
103+
assert.approximately(result[2], 0.5, accuracy);
104+
});
105+
106+
test('50% brightness red: HSB(0, 100, 50) → RGB(0.5, 0, 0)', function() {
107+
const result = HSBSpace.toBase([0, 100, 50]);
108+
assert.approximately(result[0], 0.5, accuracy);
109+
assert.approximately(result[1], 0, accuracy);
110+
assert.approximately(result[2], 0, accuracy);
111+
});
112+
});
113+
114+
suite('Edge Cases', function() {
115+
test('hue at 360 should be same as 0 (red)', function() {
116+
const result = HSBSpace.toBase([360, 100, 100]);
117+
assert.approximately(result[0], 1, accuracy);
118+
assert.approximately(result[1], 0, accuracy);
119+
assert.approximately(result[2], 0, accuracy);
120+
});
121+
122+
test('brightness 0 produces black regardless of hue/saturation', function() {
123+
const result = HSBSpace.toBase([120, 100, 0]);
124+
assert.approximately(result[0], 0, accuracy);
125+
assert.approximately(result[1], 0, accuracy);
126+
assert.approximately(result[2], 0, accuracy);
127+
});
128+
});
129+
});
130+
131+
suite('RGB to HSB conversion (fromBase)', function() {
132+
suite('Primary Colors', function() {
133+
test('pure red: RGB(1, 0, 0) → HSB(0, 100, 100)', function() {
134+
const result = HSBSpace.fromBase([1, 0, 0]);
135+
assert.approximately(result[0], 0, accuracy);
136+
assert.approximately(result[1], 100, accuracy);
137+
assert.approximately(result[2], 100, accuracy);
138+
});
139+
140+
test('pure green: RGB(0, 1, 0) → HSB(120, 100, 100)', function() {
141+
const result = HSBSpace.fromBase([0, 1, 0]);
142+
assert.approximately(result[0], 120, accuracy);
143+
assert.approximately(result[1], 100, accuracy);
144+
assert.approximately(result[2], 100, accuracy);
145+
});
146+
147+
test('pure blue: RGB(0, 0, 1) → HSB(240, 100, 100)', function() {
148+
const result = HSBSpace.fromBase([0, 0, 1]);
149+
assert.approximately(result[0], 240, accuracy);
150+
assert.approximately(result[1], 100, accuracy);
151+
assert.approximately(result[2], 100, accuracy);
152+
});
153+
});
154+
155+
suite('Secondary Colors', function() {
156+
test('yellow: RGB(1, 1, 0) → HSB(60, 100, 100)', function() {
157+
const result = HSBSpace.fromBase([1, 1, 0]);
158+
assert.approximately(result[0], 60, accuracy);
159+
assert.approximately(result[1], 100, accuracy);
160+
assert.approximately(result[2], 100, accuracy);
161+
});
162+
163+
test('cyan: RGB(0, 1, 1) → HSB(180, 100, 100)', function() {
164+
const result = HSBSpace.fromBase([0, 1, 1]);
165+
assert.approximately(result[0], 180, accuracy);
166+
assert.approximately(result[1], 100, accuracy);
167+
assert.approximately(result[2], 100, accuracy);
168+
});
169+
170+
test('magenta: RGB(1, 0, 1) → HSB(300, 100, 100)', function() {
171+
const result = HSBSpace.fromBase([1, 0, 1]);
172+
assert.approximately(result[0], 300, accuracy);
173+
assert.approximately(result[1], 100, accuracy);
174+
assert.approximately(result[2], 100, accuracy);
175+
});
176+
});
177+
178+
suite('Grayscale', function() {
179+
test('white: RGB(1, 1, 1) → HSB(0, 0, 100)', function() {
180+
const result = HSBSpace.fromBase([1, 1, 1]);
181+
assert.approximately(result[0], 0, accuracy);
182+
assert.approximately(result[1], 0, accuracy);
183+
assert.approximately(result[2], 100, accuracy);
184+
});
185+
186+
test('black: RGB(0, 0, 0) → HSB(0, 0, 0)', function() {
187+
const result = HSBSpace.fromBase([0, 0, 0]);
188+
assert.approximately(result[0], 0, accuracy);
189+
assert.approximately(result[1], 0, accuracy);
190+
assert.approximately(result[2], 0, accuracy);
191+
});
192+
193+
test('mid gray: RGB(0.5, 0.5, 0.5) → HSB(0, 0, 50)', function() {
194+
const result = HSBSpace.fromBase([0.5, 0.5, 0.5]);
195+
assert.approximately(result[0], 0, accuracy);
196+
assert.approximately(result[1], 0, accuracy);
197+
assert.approximately(result[2], 50, accuracy);
198+
});
199+
});
200+
201+
suite('Partial Values', function() {
202+
test('dark red: RGB(0.5, 0, 0) → HSB(0, 100, 50)', function() {
203+
const result = HSBSpace.fromBase([0.5, 0, 0]);
204+
assert.approximately(result[0], 0, accuracy);
205+
assert.approximately(result[1], 100, accuracy);
206+
assert.approximately(result[2], 50, accuracy);
207+
});
208+
209+
test('light red (pink): RGB(1, 0.5, 0.5) → HSB(0, 50, 100)', function() {
210+
const result = HSBSpace.fromBase([1, 0.5, 0.5]);
211+
assert.approximately(result[0], 0, accuracy);
212+
assert.approximately(result[1], 50, accuracy);
213+
assert.approximately(result[2], 100, accuracy);
214+
});
215+
});
216+
});
217+
218+
suite('Round-trip conversion', function() {
219+
test('HSB → RGB → HSB should preserve values', function() {
220+
const originalHSB = [210, 75, 80];
221+
const rgb = HSBSpace.toBase(originalHSB);
222+
const resultHSB = HSBSpace.fromBase(rgb);
223+
224+
assert.approximately(resultHSB[0], originalHSB[0], 0.1);
225+
assert.approximately(resultHSB[1], originalHSB[1], 0.1);
226+
assert.approximately(resultHSB[2], originalHSB[2], 0.1);
227+
});
228+
229+
test('RGB → HSB → RGB should preserve values', function() {
230+
const originalRGB = [0.7, 0.3, 0.5];
231+
const hsb = HSBSpace.fromBase(originalRGB);
232+
const resultRGB = HSBSpace.toBase(hsb);
233+
234+
assert.approximately(resultRGB[0], originalRGB[0], 0.01);
235+
assert.approximately(resultRGB[1], originalRGB[1], 0.01);
236+
assert.approximately(resultRGB[2], originalRGB[2], 0.01);
237+
});
238+
});
239+
});

0 commit comments

Comments
 (0)