Skip to content

Commit

Permalink
almost done, just writing tests for functions
Browse files Browse the repository at this point in the history
  • Loading branch information
landonwjohnson committed Jul 17, 2024
1 parent 492dc60 commit 1ff43b9
Show file tree
Hide file tree
Showing 21 changed files with 242 additions and 155 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,6 @@
"typedoc": "^0.25.8"
},
"dependencies": {
"@devlander/utils": "^0.0.63"
"@devlander/utils": "^0.0.66"
}
}
4 changes: 2 additions & 2 deletions src/__tests__/adjustColor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ describe('adjustColor', () => {

it('should apply alpha to RGB color', () => {
const result = adjustColor('rgb(0, 0, 0)', 0.5 as AlphaValue, 'light');
expect(result).toMatch(/^rgba\(\d{1,3}, \d{1,3}, \d{1,3}, \d(\.\d+)?\)$/i); // Regex to match RGBA color
expect(result).toMatch(/^rgba\(\d{1,3}, \d{1,3}, \d{1,3}, 0(\.\d+)?\)$/i); // Regex to match RGBA color
});

it('should apply alpha to RGBA color', () => {
const result = adjustColor('rgba(0, 0, 0, 1)', 0.5 as AlphaValue, 'light');
expect(result).toMatch(/^rgba\(\d{1,3}, \d{1,3}, \d{1,3}, \d(\.\d+)?\)$/i); // Regex to match RGBA color
expect(result).toMatch(/^rgba\(\d{1,3}, \d{1,3}, \d{1,3}, 0(\.\d+)?\)$/i); // Regex to match RGBA color
});

it('should handle exceptions and return default color', () => {
Expand Down
8 changes: 1 addition & 7 deletions src/__tests__/formatDecimalObjectToRgba.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,5 @@ describe('formatDecimalObjectToRgba', () => {
expect(formatDecimalObjectToRgba(color, 'invalid')).toBe('rgba(255, 255, 255, 1)');
});

test('returns empty string on error', () => {
jest.spyOn(console, 'error').mockImplementation(() => {}); // Mock console.error
const invalidColor = null as unknown as HexDecimalObject; // Force an error
expect(formatDecimalObjectToRgba(invalidColor)).toBe('');
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Error formatting decimal object to RGBA string'));
(console.error as jest.Mock).mockRestore();
});

});
2 changes: 1 addition & 1 deletion src/__tests__/hexToRgb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ describe("hexToRgb", () => {
const hexWithAlpha = "#B20A28FF";
const rgbWithAlpha = hexToRgb(hexWithAlpha);
// this should round up
expect(rgbWithAlpha).toBe("rgba(178, 10, 40, 0.6980392156862745)");
expect(rgbWithAlpha).toBe("rgba(178, 10, 40, 0.7)");
});
});
40 changes: 33 additions & 7 deletions src/__tests__/isValidRgb.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,33 @@
export const isValidRgb = (rgb: string): boolean => {
const rgbRegex = /^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/;
const match = rgb.match(rgbRegex);
if (!match) return false;
const [, r, g, b] = match.map(Number);
return r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
};
import { isValidRgb } from "../isValidRgb";

describe("isValidRgb", () => {
test("validates correctly formatted RGB strings", () => {
expect(isValidRgb("rgb(255, 0, 128)")).toBe(true);
expect(isValidRgb("rgb(0, 128, 255)")).toBe(true);
expect(isValidRgb("rgb(100, 100, 100)")).toBe(true);
});

test("handles edge cases", () => {
expect(isValidRgb("rgb(0,0,0)")).toBe(true); // No spaces
expect(isValidRgb("rgb(255, 255, 255)")).toBe(true); // Maximum values
expect(isValidRgb("rgb(256, 255, 255)")).toBe(false); // Out of range
expect(isValidRgb("rgb(255, 256, 255)")).toBe(false); // Out of range
expect(isValidRgb("rgb(255, 255, 256)")).toBe(false); // Out of range
expect(isValidRgb("rgb(-1, 0, 128)")).toBe(false); // Negative value
expect(isValidRgb("rgb(255, 0, 128")).toBe(false); // Missing closing parenthesis
expect(isValidRgb("rgba(255, 0, 128)")).toBe(false); // Wrong format
expect(isValidRgb("rgb(255, 0)")).toBe(false); // Missing a component
expect(isValidRgb("rgb(255, 0, 128, 0.5)")).toBe(false); // Extra alpha component
expect(isValidRgb("rgb(255, 0, 128,)")).toBe(false); // Trailing comma
expect(isValidRgb("rgb(255, 0, 128")).toBe(false); // Missing closing parenthesis
});

test("handles invalid input gracefully", () => {
expect(isValidRgb("")).toBe(false); // Empty string
expect(isValidRgb("rgb")).toBe(false); // Missing parentheses and numbers
expect(isValidRgb("rgb()")).toBe(false); // Empty parentheses
expect(isValidRgb("rgb(255, 0, 128, extra)")).toBe(false); // Non-numeric component
expect(isValidRgb("rgb(255, 0, 128," + "\n" + ")")).toBe(false); // Newline between components
expect(isValidRgb("rgb(255, 0, 128) extra")).toBe(false); // Extra characters after valid format
});
});
35 changes: 35 additions & 0 deletions src/__tests__/isValidRgba.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { isValidRgba } from "../isValidRgba";

describe("isValidRgba", () => {
test("validates correctly formatted RGBA strings", () => {
expect(isValidRgba("rgba(255, 0, 128, 0.5)")).toBe(true);
expect(isValidRgba("rgba(0, 128, 255, 1)")).toBe(true);
expect(isValidRgba("rgba(100, 100, 100, 0)")).toBe(true);
expect(isValidRgba("rgba(255, 255, 255, 0.75)")).toBe(true);
expect(isValidRgba("rgb(255, 0, 0)")).toBe(true); // Should also validate RGB strings
});

test("handles edge cases", () => {
expect(isValidRgba("rgba(0,0,0,0)")).toBe(true); // No spaces
expect(isValidRgba("rgba(255, 255, 255, 1)")).toBe(true); // Maximum values
expect(isValidRgba("rgba(256, 255, 255, 0.5)")).toBe(false); // Out of range RGB
expect(isValidRgba("rgba(255, 256, 255, 0.5)")).toBe(false); // Out of range RGB
expect(isValidRgba("rgba(255, 255, 256, 0.5)")).toBe(false); // Out of range RGB
expect(isValidRgba("rgba(-1, 0, 128, 0.5)")).toBe(false); // Negative value
expect(isValidRgba("rgba(255, 0, 128")).toBe(false); // Missing closing parenthesis
expect(isValidRgba("rgba(255, 0, 128,")).toBe(false); // Trailing comma
expect(isValidRgba("rgba(255, 0, 128, extra)")).toBe(false); // Non-numeric alpha
expect(isValidRgba("rgba(255, 0, 128, 0.5, extra)")).toBe(false); // Extra alpha component
expect(isValidRgba("rgba(255, 0, 128, 0.5")).toBe(false); // Missing closing parenthesis
expect(isValidRgba("rgba(255, 0, 128 extra")).toBe(false); // Extra characters
expect(isValidRgba("rgba(255, 0, 128) extra")).toBe(false); // Extra characters after valid format
});

test("handles invalid input gracefully", () => {
expect(isValidRgba("")).toBe(false); // Empty string
expect(isValidRgba("rgba")).toBe(false); // Missing parentheses and numbers
expect(isValidRgba("rgba()")).toBe(false); // Empty parentheses
expect(isValidRgba("rgba(255, 0, 128, extra)")).toBe(false); // Non-numeric component
expect(isValidRgba("rgba(255, 0, 128," + "\n" + ")")).toBe(false); // Newline between components
});
});
38 changes: 38 additions & 0 deletions src/__tests__/parseRgbString.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { parseRgbString } from "../parseRgbString";

describe('parseRgbString', () => {
it('should return parsed RGB object for valid RGB string', () => {
const result = parseRgbString('rgb(255, 255, 255)');
expect(result).toEqual({ r: 255, g: 255, b: 255 });
});

it('should return parsed RGBA object for valid RGBA string', () => {
const result = parseRgbString('rgba(255, 255, 255, 0.5)');
expect(result).toEqual({ r: 255, g: 255, b: 255, a: 0.5 });
});

it('should return null for invalid RGB string', () => {
const result = parseRgbString('rgb(255, 255, 255, 1)');
expect(result).toBeNull();
});

it('should return null for invalid RGBA string', () => {
const result = parseRgbString('rgba(255, 255, 255)');
expect(result).toBeNull();
});

it('should return null for completely invalid string', () => {
const result = parseRgbString('invalid string');
expect(result).toBeNull();
});

it('should handle errors and return null', () => {
jest.spyOn(console, 'error').mockImplementation(() => {}); // Mock console.error

const result = parseRgbString('rgb(255, 255, not-a-number)');
expect(result).toBeNull();
expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Error parsing RGB string'));

(console.error as jest.Mock).mockRestore();
});
});
1 change: 0 additions & 1 deletion src/adjustColor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export const adjustColor: AdjustColorFunc = (
cssColorNames = defaultCssColorNames
): string => {
try {
// Returning this since you can't get a hex code for transparent or reverse it
if (cssColorNames.includes(colorValue)) return colorValue;

if (alphaValue < 0 || alphaValue > 1) {
Expand Down
4 changes: 2 additions & 2 deletions src/formatDecimalObjectToRgba.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const formatDecimalObjectToRgba = (
: parsedA;
return toRgbString({ r, g, b, a });
} catch (error) {
console.error('Error formatting decimal object to RGBA string:', error);
return '';
console.error('Error formatting decimal object to RGBA string:', error);
return toRgbString({ r: 0, g: 0, b: 0, a: 1 });
}
};
59 changes: 0 additions & 59 deletions src/generateColorFrom[TODO].ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/hexToDecimals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const hexToDecimal = (hex: string): number => {
};

export interface RgbWithAHexObject extends Partial<HexObject >{
r: string,
r: string
g: string,
b: string,
a?: string
Expand Down
66 changes: 44 additions & 22 deletions src/hexToRgba.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isNumeric } from '@devlander/utils';
import { hexToDecimal } from './hexToDecimals';
import { isValidHex } from './isValidHex';
import { parseHex } from './parseHex';
Expand All @@ -6,33 +7,54 @@ import { toRgbString } from './toRgbString';
/**
* Converts a CSS hex color value to an RGB or RGBA color value.
* @param hex - The hex value to convert. ('123456', '#123456', '123', '#123')
* @param alpha - An optional alpha value to apply. ('0.5', '0.25')
* @param alpha - An optional alpha value to apply. ('0.5', '0.25', 0.5, 0.25)
* @returns An RGB or RGBA color value. ('rgb(11, 22, 33)', 'rgba(11, 22, 33, 0.5)')
*
* @example
* ```typescript
* console.log(hexToRgba('#ff0000')); // 'rgba(255, 0, 0, 1)'
* console.log(hexToRgba('#ff0000', 0.5)); // 'rgba(255, 0, 0, 0.5)'
* ```
*/
export function hexToRgba(hex: string, alpha: string | number = 1): string {
if (!isValidHex(hex)) {
throw new Error('Invalid hex color');
}
try {
if (!isValidHex(hex)) {
throw new Error('Invalid hex color');
}

const hashlessHex = hex.replace(/^#/, '');
const { r, g, b } = parseHex(hashlessHex);
const hashlessHex = hex.replace(/^#/, '');
const { r, g, b } = parseHex(hashlessHex);

if (typeof alpha === 'number' && (alpha < 0 || alpha > 1)) {
throw new Error('Invalid alpha value');
}
// Check if r, g, b are valid numbers
if (!isNumeric(r) || !isNumeric(g) || !isNumeric(b)) {
throw new TypeError('Invalid color components');
}

let alphaValue: number;

const alphaValue = typeof alpha === 'number' ? alpha : isNaN(parseFloat(alpha)) ? 1 : parseFloat(alpha);
// Check alpha value
if (typeof alpha === 'number') {
if (alpha < 0 || alpha > 1) {
throw new Error('Invalid alpha value');
}
alphaValue = alpha;
} else if (isNumeric(alpha)) {
alphaValue = parseFloat(alpha);
if (alphaValue < 0 || alphaValue > 1) {
throw new Error('Invalid alpha value');
}
} else {
alphaValue = 1;
}

return toRgbString({
r: hexToDecimal(r),
g: hexToDecimal(g),
b: hexToDecimal(b),
a: alphaValue
});
return toRgbString({
r: hexToDecimal(r),
g: hexToDecimal(g),
b: hexToDecimal(b),
a: alphaValue
});

} catch (error: any) {
console.log(`Error converting hex to RGBA: ${error.toString()}`);
return toRgbString({
r: hexToDecimal('FF'),
g: hexToDecimal('00'),
b: hexToDecimal('00'),
a: 1
});
}
}
3 changes: 1 addition & 2 deletions src/isHexColor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@
* console.log(isHexColor(123 as any)); // false
* ```
*/

export const isHexColor = (hex: string): boolean => {
if (typeof hex !== 'string') {
console.log(`Invalid type for hex: ${typeof hex}`)
return false
}
const hexPattern =
/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/
/^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/
const isValid = hexPattern.test(hex)
console.log(`Testing hex: ${hex}, Result: ${isValid}`)
return isValid
Expand Down
26 changes: 21 additions & 5 deletions src/isValidRgb.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
/**
* Checks if the provided string is a valid RGB color format.
* @param rgb The string to validate as RGB (e.g., "rgb(255, 0, 128)").
* @returns True if the string is a valid RGB format, false otherwise.
*/
export const isValidRgb = (rgb: string): boolean => {
const rgbRegex = /^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/;
const match = rgb.match(rgbRegex);
if (!match) return false;
const [, r, g, b] = match.map(Number);
return r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
try {
const rgbRegex = /^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/;
const match = rgb.match(rgbRegex);

if (!match) {
return false;
}

const [, r, g, b] = match.map(Number);

// Check if components are within valid range
return r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
} catch (error) {
console.error(`Error validating RGB string: ${rgb}`, error);
return false;
}
};
Loading

0 comments on commit 1ff43b9

Please sign in to comment.