|
1 |
| -import { describe, it, expect } from 'vitest'; |
2 |
| -import { z } from 'zod'; |
3 |
| -import { |
4 |
| - compareFunction, |
5 |
| - formatIP, |
6 |
| - getFormatedKubeVersion, |
7 |
| - isIPValid, |
8 |
| - paginateResults, |
9 |
| - getColorByPercentage, |
10 |
| - camelToSnake, |
11 |
| - filterSchemaKeys, |
12 |
| - isBase64, |
13 |
| - parseCommaSeparated, |
14 |
| - generateUniqueName, |
15 |
| -} from '@/helpers/index'; |
16 |
| -import { NodePool } from '@/api/data/kubernetes'; |
17 |
| - |
18 |
| -describe('helper', () => { |
19 |
| - it('compares two objects based on a key', () => { |
20 |
| - const obj1 = { name: 'Alice' }; |
21 |
| - const obj2 = { name: 'Bob' }; |
22 |
| - const result = compareFunction('name')(obj1, obj2); |
23 |
| - expect(result).toBeLessThan(0); |
24 |
| - }); |
25 |
| - |
26 |
| - it('paginates results correctly', () => { |
27 |
| - const items = Array.from({ length: 10 }, (_, i) => ({ id: i })); |
28 |
| - const pagination = { pageIndex: 1, pageSize: 5 }; |
29 |
| - const result = paginateResults(items, pagination); |
30 |
| - expect(result.rows).toHaveLength(5); |
31 |
| - expect(result.pageCount).toBe(2); |
32 |
| - expect(result.totalRows).toBe(10); |
33 |
| - }); |
34 |
| - |
35 |
| - describe('getFormatedKubeVersion', () => { |
36 |
| - it.each([ |
37 |
| - ['1.32.1-1', '1.32'], |
38 |
| - ['1.32', '1.32'], |
39 |
| - ['1.32.0', '1.32'], |
40 |
| - ['1.32.1', '1.32'], |
41 |
| - ['1', '1'], |
42 |
| - ])('retourne la version formatée pour %s', (version, expected) => { |
43 |
| - expect(getFormatedKubeVersion(version)).toBe(expected); |
44 |
| - }); |
45 |
| - }); |
46 |
| - |
47 |
| - it('formats IP with default mask if not provided', () => { |
48 |
| - const ip = '192.168.1.1'; |
49 |
| - const result = formatIP(ip); |
50 |
| - expect(result).toBe('192.168.1.1/32'); |
51 |
| - }); |
52 |
| - |
53 |
| - it('formats IP with provided mask', () => { |
54 |
| - const ip = '192.168.1.1/24'; |
55 |
| - const result = formatIP(ip); |
56 |
| - expect(result).toBe('192.168.1.1/24'); |
57 |
| - }); |
58 |
| - |
59 |
| - it('validates correct IP without mask', () => { |
60 |
| - const ip = '192.168.1.1'; |
61 |
| - const result = isIPValid(ip); |
62 |
| - expect(result).toBe(true); |
63 |
| - }); |
64 |
| - |
65 |
| - it('validates correct IP with mask', () => { |
66 |
| - const ip = '192.168.1.1/24'; |
67 |
| - const result = isIPValid(ip); |
68 |
| - expect(result).toBe(true); |
69 |
| - }); |
70 |
| - |
71 |
| - it('invalidates incorrect IP', () => { |
72 |
| - const ip = '999.999.999.999'; |
73 |
| - const result = isIPValid(ip); |
74 |
| - expect(result).toBe(false); |
75 |
| - }); |
76 |
| - |
77 |
| - it('invalidates IP with incorrect mask', () => { |
78 |
| - const ip = '192.168.1.1/999'; |
79 |
| - const result = isIPValid(ip); |
80 |
| - expect(result).toBe(false); |
81 |
| - }); |
82 |
| -}); |
83 |
| - |
84 |
| -describe('getColorByPercentage', () => { |
85 |
| - it('should return primary color for percentage <= 69', () => { |
86 |
| - expect(getColorByPercentage(50)).toBe('var(--ods-color-primary-500)'); |
87 |
| - expect(getColorByPercentage(69)).toBe('var(--ods-color-primary-500)'); |
88 |
| - }); |
89 |
| - |
90 |
| - it('should return warning color for percentage between 70 and 79', () => { |
91 |
| - expect(getColorByPercentage(75)).toBe('var(--ods-color-warning-500)'); |
92 |
| - }); |
93 |
| - |
94 |
| - it('should return error color for percentage between 80 and 100', () => { |
95 |
| - expect(getColorByPercentage(85)).toBe('var(--ods-color-error-500)'); |
96 |
| - expect(getColorByPercentage(100)).toBe('var(--ods-color-error-500)'); |
97 |
| - }); |
98 |
| - |
99 |
| - it('should return last color in thresholds if percentage exceeds 100', () => { |
100 |
| - expect(getColorByPercentage(120)).toBe('var(--ods-color-error-500)'); |
101 |
| - }); |
102 |
| -}); |
103 |
| - |
104 |
| -describe('camelToSnake', () => { |
105 |
| - it('converts camelCase to snake_case', () => { |
106 |
| - expect(camelToSnake('camelCase')).toBe('camel_case'); |
107 |
| - expect(camelToSnake('someLongVariableName')).toBe( |
108 |
| - 'some_long_variable_name', |
109 |
| - ); |
110 |
| - expect(camelToSnake('already_snake_case')).toBe('already_snake_case'); |
111 |
| - }); |
112 |
| -}); |
113 |
| - |
114 |
| -describe('filterSchemaKeys', () => { |
115 |
| - it('filters out keys from schema based on exclude list', () => { |
116 |
| - const schema = z.object({ |
117 |
| - key1: z.string(), |
118 |
| - key2: z.number(), |
119 |
| - key3: z.boolean(), |
120 |
| - }); |
121 |
| - const result = filterSchemaKeys(schema, ['key2']); |
122 |
| - expect(result).toEqual(['key1', 'key3']); |
123 |
| - }); |
124 |
| - |
125 |
| - it('returns all keys if exclude list is empty', () => { |
126 |
| - const schema = z.object({ |
127 |
| - key1: z.string(), |
128 |
| - key2: z.number(), |
129 |
| - }); |
130 |
| - const result = filterSchemaKeys(schema, []); |
131 |
| - expect(result).toEqual(['key1', 'key2']); |
132 |
| - }); |
133 |
| - |
134 |
| - it('returns no keys if all are excluded', () => { |
135 |
| - const schema = z.object({ |
136 |
| - key1: z.string(), |
137 |
| - key2: z.number(), |
| 1 | +import { AutoscalingState } from '@/components/Autoscaling.component'; |
| 2 | +import { KubeFlavor } from '@/components/flavor-selector/FlavorSelector.component'; |
| 3 | +import { getPrice } from '.'; |
| 4 | + |
| 5 | +describe('getPrice', () => { |
| 6 | + const testCases = [ |
| 7 | + { |
| 8 | + description: 'flavor et scaling with monthly', |
| 9 | + flavor: { |
| 10 | + pricingsHourly: { price: 0.1 }, |
| 11 | + pricingsMonthly: { price: 50 }, |
| 12 | + }, |
| 13 | + scaling: { |
| 14 | + quantity: { desired: 2 }, |
| 15 | + }, |
| 16 | + expected: { |
| 17 | + hour: 0.2, |
| 18 | + month: 100, |
| 19 | + }, |
| 20 | + }, |
| 21 | + { |
| 22 | + description: 'flavor et scaling without monthly', |
| 23 | + flavor: { |
| 24 | + pricingsHourly: { price: 0.01 }, |
| 25 | + pricingsMonthly: null, |
| 26 | + }, |
| 27 | + scaling: { |
| 28 | + quantity: { desired: 3 }, |
| 29 | + }, |
| 30 | + expected: { |
| 31 | + hour: 0.03, |
| 32 | + month: undefined, |
| 33 | + }, |
| 34 | + }, |
| 35 | + { |
| 36 | + description: 'scaling null', |
| 37 | + flavor: { |
| 38 | + pricingsHourly: { price: 0.1 }, |
| 39 | + pricingsMonthly: { price: 50 }, |
| 40 | + }, |
| 41 | + scaling: null, |
| 42 | + expected: undefined, |
| 43 | + }, |
| 44 | + { |
| 45 | + description: 'flavor null', |
| 46 | + flavor: null, |
| 47 | + scaling: { |
| 48 | + quantity: { desired: 2 }, |
| 49 | + }, |
| 50 | + expected: undefined, |
| 51 | + }, |
| 52 | + ]; |
| 53 | + |
| 54 | + (testCases as { |
| 55 | + description: string; |
| 56 | + flavor: KubeFlavor | null; |
| 57 | + scaling: AutoscalingState | null; |
| 58 | + expected: { hour: number; month?: number } | undefined; |
| 59 | + }[]).forEach(({ description, flavor, scaling, expected }) => { |
| 60 | + it(`should return correct pricing when ${description}`, () => { |
| 61 | + const result = getPrice(flavor, scaling); |
| 62 | + expect(result).toEqual(expected); |
138 | 63 | });
|
139 |
| - const result = filterSchemaKeys(schema, ['key1', 'key2']); |
140 |
| - expect(result).toEqual([]); |
141 |
| - }); |
142 |
| -}); |
143 |
| - |
144 |
| -describe('parseCommaSeparated', () => { |
145 |
| - it('parses a comma-separated string into an array', () => { |
146 |
| - expect(parseCommaSeparated('a,b,c')).toEqual(['a', 'b', 'c']); |
147 |
| - }); |
148 |
| - |
149 |
| - it('trims spaces around values', () => { |
150 |
| - expect(parseCommaSeparated(' a , b , c ')).toEqual(['a', 'b', 'c']); |
151 | 64 | });
|
152 |
| - |
153 |
| - it('removes empty values', () => { |
154 |
| - expect(parseCommaSeparated('a,,b,c,,')).toEqual(['a', 'b', 'c']); |
155 |
| - }); |
156 |
| - |
157 |
| - it('handles arrays directly', () => { |
158 |
| - expect(parseCommaSeparated(['a', ' b ', 'c'])).toEqual(['a', 'b', 'c']); |
159 |
| - }); |
160 |
| - |
161 |
| - it('returns an empty array for undefined input', () => { |
162 |
| - expect(parseCommaSeparated(undefined)).toEqual([]); |
163 |
| - }); |
164 |
| -}); |
165 |
| - |
166 |
| -describe('isBase64', () => { |
167 |
| - it('validates a correct Base64 string', () => { |
168 |
| - expect(isBase64('SGVsbG8gd29ybGQ=')).toBe(true); |
169 |
| - }); |
170 |
| - |
171 |
| - it('invalidates a non-Base64 string', () => { |
172 |
| - expect(isBase64('NotBase64')).toBe(false); |
173 |
| - }); |
174 |
| - |
175 |
| - it('invalidates a malformed Base64 string', () => { |
176 |
| - expect(isBase64('SGVsbG8gd29ybGQ')).toBe(false); |
177 |
| - }); |
178 |
| -}); |
179 |
| - |
180 |
| -describe('generateUniqueName', () => { |
181 |
| - it.each([ |
182 |
| - ['NodePool-2', [{ name: 'NodePool-1' }], 'NodePool-2'], |
183 |
| - ['NodePool-2', [{ name: 'NodePool-2' }], 'NodePool-2-1'], |
184 |
| - [ |
185 |
| - 'NodePool-2', |
186 |
| - [ |
187 |
| - { name: 'NodePool-2' }, |
188 |
| - { name: 'NodePool-2-1' }, |
189 |
| - { name: 'NodePool-2-2' }, |
190 |
| - ], |
191 |
| - 'NodePool-2-3', |
192 |
| - ], |
193 |
| - [ |
194 |
| - 'UniquePool', |
195 |
| - [{ name: 'AnotherPool' }, { name: 'NodePool-2' }], |
196 |
| - 'UniquePool', |
197 |
| - ], |
198 |
| - ])( |
199 |
| - 'should return %s for baseName "%s" with existing nodes %j', |
200 |
| - (baseName, existingNodePools, expectedResult) => { |
201 |
| - const result = generateUniqueName( |
202 |
| - baseName, |
203 |
| - existingNodePools as NodePool[], |
204 |
| - ); |
205 |
| - expect(result).toBe(expectedResult); |
206 |
| - }, |
207 |
| - ); |
208 | 65 | });
|
0 commit comments