Compare commits

...

7 Commits

Author SHA1 Message Date
5ca2e7a358 tp note fini 2024-04-18 15:17:12 +02:00
4df48587df gitignore 2024-04-18 12:41:50 +02:00
5573b6d6a5 1/2j 2024-04-18 12:33:15 +02:00
e092272bd4 debut TP2 2024-04-18 09:43:42 +02:00
a17920df41 fin tp 2024-03-29 16:57:33 +01:00
eb3de77bd9 gitignore 2024-03-29 12:26:04 +01:00
08351ec94f readme 2024-03-29 12:25:11 +01:00
43 changed files with 951 additions and 91 deletions

4
.gitignore vendored
View File

@ -5,3 +5,7 @@ package-lock.json
.idea/inspectionProfiles/
.idea/
.vscode/
coverage/

43
.vscode/launch.json vendored
View File

@ -1,43 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Start app",
"request": "launch",
"runtimeArgs": ["run-script", "start"],
"runtimeExecutable": "npm",
"skipFiles": ["<node_internals>/**"],
"type": "node",
"sourceMaps": true,
"console": "integratedTerminal"
},
{
"name": "Debug app",
"request": "launch",
"runtimeArgs": ["run-script", "dev", "debug"],
"runtimeExecutable": "npm",
"skipFiles": ["<node_internals>/**"],
"type": "node",
"sourceMaps": true,
"console": "integratedTerminal"
},
{
"type": "node",
"request": "launch",
"name": "Jest All",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["--runInBand"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"type": "node",
"request": "launch",
"name": "Jest Current File",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["${fileBasenameNoExtension}", "--config", "jest.config.js"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}

View File

@ -1 +1,2 @@
# unit-test-template-typescript
# Méthodologies de tests et tests unitaires

View File

@ -23,8 +23,8 @@
},
"dependencies": {
"nodemon": "^3.1.0",
"reflect-metadata": "^0.2.1",
"reflect-metadata": "^0.2.2",
"ts-node": "^10.9.2",
"tsyringe": "^4.8.0"
}
}
}

View File

@ -0,0 +1,21 @@
import {removeDuplicates} from "./index";
describe("Test removeDuplicates", () => {
it.each([
{ arr: [3, 2, 4, 3, 5, 2], expected: [3, 2, 4, 5] },
{ arr: [1, 1, 1, 1, 1], expected: [1] },
{ arr: [1, 2, 3, 4, 5], expected: [1, 2, 3, 4, 5] }
])(
"should remove duplicates from array",
({ arr, expected }) => {
const result = removeDuplicates(arr);
expect(result).toEqual(expected);
console.log(`Test with array = ${arr}, expected = ${expected}, result = ${result}`);
}
);
it("should throw an exception when the array is empty", () => {
const emptyArray: number[] = [];
expect(() => removeDuplicates(emptyArray)).toThrowError("Le tableau est vide.");
});
});

View File

@ -0,0 +1,13 @@
export function removeDuplicates(arr: number[]): number[] {
if (arr.length === 0) {
throw new Error("Le tableau est vide.");
}
const uniqueArray: number[] = [];
arr.forEach((num) => {
if (!uniqueArray.includes(num)) {
uniqueArray.push(num);
}
});
return uniqueArray;
}

View File

@ -0,0 +1,57 @@
import { fibo } from "./index";
describe("fibo", () => {
it("should return 0 when given 0", () => {
// arrange
const input = 0;
const expected = 0;
// act
const result = fibo(input);
// assert
expect(result).toBe(expected);
});
it("should return 1 when given 1", () => {
// arrange
const input = 1;
const expected = 1;
// act
const result = fibo(input);
// assert
expect(result).toBe(expected);
});
it.each([
{
input: 2,
expected: 1,
},
{
input: 3,
expected: 2,
},
{
input: 4,
expected: 3,
},
{
input: 5,
expected: 5,
},
{
input: 6,
expected: 8,
},
])("should return fibo(n) when given n", ({ input, expected }) => {
// arrange
// act
const result = fibo(input);
// assert
expect(result).toBe(expected);
});
});

View File

@ -0,0 +1,5 @@
export function fibo(n: number): number {
if (n <= 1) return n;
return fibo(n - 2) + fibo(n - 1);
}

View File

@ -0,0 +1,64 @@
import { fizzBuzz } from "./index";
describe("fizzBuzz", () => {
it.each([
{
input: 1,
expected: "1",
},
{
input: 2,
expected: "2",
},
{
input: 4,
expected: "4",
},
])(
"should return the number as string when given a non multiple of 3, 5 or 15",
({ input, expected }) => {
// arrange
// act
const result = fizzBuzz(input);
// assert
expect(result).toBe(expected);
}
);
it.each([3, 6, 9])(
"should return 'Fizz' when given a multiple of 3",
(input) => {
// arrange
// act
const result = fizzBuzz(input);
// assert
expect(result).toBe("Fizz");
}
);
it.each([5, 10, 20])(
'should return "Buzz" when given a multiple of 5',
(input) => {
// arrange
// act
const result = fizzBuzz(input);
// assert
expect(result).toBe("Buzz");
}
);
it.each([15, 30, 45])(
'should return "FizzBuzz" when given a multiple of 15',
(input) => {
// arrange
// act
const result = fizzBuzz(input);
// assert
expect(result).toBe("FizzBuzz");
}
);
});

View File

@ -0,0 +1,7 @@
export function fizzBuzz(input: number): string {
if (input % 15 === 0) return "FizzBuzz";
if (input % 5 === 0) return "Buzz";
if (input % 3 === 0) return "Fizz";
return input.toString();
}

View File

@ -1,32 +0,0 @@
import { divide } from "./index";
describe("Test divide", () => {
it.each([
{ foo: "", bar: "", expected: "" },
])(
"should $foo $bar",
({ foo, bar, expected }) => {
// act
// const result = function (foo, bar);
const result = 0;
// assert
expect(result).toEqual(expected);
console.log(`Test with foo = ${foo}, bar = ${bar}, expected = ${expected}, result = ${result}`);
}
);
/*
*
* If exception test
*
* */
it("should throw an exception when dividing by zero", () => {
// arrange
const foo = "";
const bar = "";
// act & assert
///TODO
// expect(() => function (foo, bar).toThrow("E");
console.log(foo + bar);
});
});

View File

@ -1,3 +0,0 @@
export function name(foo : number) : number {
return foo + 1;
}

View File

@ -0,0 +1,115 @@
import { addStringOfNumbers } from "./index";
describe("addStringOfNumbers", () => {
it("should return 0 when given an empty string", () => {
// arrange
const input = "";
const expected = 0;
// act
const result = addStringOfNumbers(input);
// assert
expect(result).toBe(expected);
});
it.each([
{ input: "12", expected: 12 },
{ input: "1.5", expected: 1.5 },
{ input: "-2", expected: -2 },
{ input: "-2.333", expected: -2.333 },
])(
"should return n when given the string representation of n",
({ input, expected }) => {
// arrange
// act
const result = addStringOfNumbers(input);
// assert
expect(result).toBe(expected);
}
);
it.each(["--4", "1-23", "3..5"])(
"should throw an error when given a string that is not a number",
(input) => {
// arrange
// act
const act = () => addStringOfNumbers(input);
// assert
expect(act).toThrow("Not valid number");
}
);
it.each([
{ input: "2,3", expected: 5 },
{ input: "-2.5,4", expected: 1.5 },
{ input: "1,2,5,9", expected: 17 },
{ input: "1,-3.2,3.7,2", expected: 3.5 },
])(
"should add any quantity of comma separated numbers in a string",
({ input, expected }) => {
// arrange
// act
const result = addStringOfNumbers(input);
// assert
expect(result).toBe(expected);
}
);
it("should throw when given a string with wrong separator", () => {
// arrange
const input = "-2.5;3";
// act
const act = () => addStringOfNumbers(input);
// assert
expect(act).toThrow("Invalid characters");
});
it.each([
{ input: "//;\n1;2", expected: 3 },
{ input: "//:\n-2.5:4", expected: 1.5 },
{ input: "//;\n1;2;5;9", expected: 17 },
])(
"should add any quantity of numbers separated by a custom character in a string",
({ input, expected }) => {
// arrange
// act
const result = addStringOfNumbers(input);
// assert
expect(result).toBe(expected);
}
);
it.each(["//.\n1.2", "//-\n-2.5-4"])(
"should throw when the custom separator is not valid",
(input) => {
// arrange
// act
const act = () => addStringOfNumbers(input);
// assert
expect(act).toThrow("Invalid custom separator");
}
);
it.each([
{ input: "//;;;\n1;;;2", expected: 3 },
{ input: "//::\n-2.5::4", expected: 1.5 },
])(
"should add any quantity of numbers separated by a custom character in a string",
({ input, expected }) => {
// arrange
// act
const result = addStringOfNumbers(input);
// assert
expect(result).toBe(expected);
}
);
});

View File

@ -0,0 +1,41 @@
const defaultSeparator = ",";
export function addStringOfNumbers(input: string) {
if (input === "") return 0;
const customSeparatorMatches = input.match(/^\/\/(.+)\n/);
const customSeparator = customSeparatorMatches
? customSeparatorMatches[1]
: null;
const separator = customSeparator || defaultSeparator;
const isContainingBadSeparator = /[-.]/.test(separator);
if (isContainingBadSeparator) throw new Error("Invalid custom separator");
const isSeparatorMadeWithSameCharacters = !separator
.split("")
.some((char) => char !== separator[0]);
if (!isSeparatorMadeWithSameCharacters)
throw new Error("Invalid custom separator");
// Regex to catch any character that is not a digit, dot, minus sign or separator
const badCharactersRegex = new RegExp(`[^-.\\d${separator}]`);
const focusedExpression = customSeparator ? input.split("\n")[1] : input;
const isContainingBadCharacters = badCharactersRegex.test(focusedExpression);
if (isContainingBadCharacters) throw new Error("Invalid characters");
if (!focusedExpression.includes(separator)) {
const num = Number(focusedExpression);
if (isNaN(num)) throw new Error("Not valid number");
return num;
}
const arr = focusedExpression.split(separator);
return arr.reduce((acc, str) => {
const num = Number(str);
if (isNaN(num)) throw new Error("Not valid numbers");
return acc + num;
}, 0);
}

View File

@ -0,0 +1,19 @@
import { convertToLowercase } from "./index";
describe("convertToLowercase", () => {
it.each([
{ input: "ToTO", expected: "toto" },
{ input: "ToTo", expected: "toto" },
{ input: "TOTo", expected: "toto" },
])(
"should return the input in lowercase when all letters are uppercases",
({ input, expected }) => {
// Arrange
// Act
const result = convertToLowercase(input);
// Assert
expect(result).toStrictEqual(expected);
}
);
});

View File

@ -0,0 +1,3 @@
export function convertToLowercase(input: string): string {
return input.toLowerCase();
}

View File

@ -1,6 +1,6 @@
import { divide } from "./index";
describe("Test divide", () => {
describe("Test hexToDecimal", () => {
it.each([
{ a: 2, b: 1, expected: 2 },
{ a: 10, b: 2, expected: 5 },

View File

@ -0,0 +1,37 @@
import { isBeforeNow } from "./index";
const dateBefore = new Date("2022-01-01T00:00:00.000Z");
const dateNow = new Date("2023-01-01T00:00:00.000Z");
const dateAfter = new Date("2024-01-01T00:00:00.000Z");
describe("isBeforeNow", () => {
beforeEach(() => {
jest.useFakeTimers({
now: dateNow,
});
// or
// jest.spyOn(Date, "now").mockReturnValue(dateNow.getTime());
});
afterEach(() => {
jest.useRealTimers();
// or
// jest.restoreAllMocks();
});
it("returns true if the date is before now", () => {
expect(isBeforeNow(dateBefore)).toBe(true);
});
it("returns false if the date is now", () => {
expect(isBeforeNow(dateNow)).toBe(false);
});
it("returns false if the date is after now", () => {
expect(isBeforeNow(dateAfter)).toBe(false);
});
});

View File

@ -0,0 +1,3 @@
export function isBeforeNow(date: Date): boolean {
return date.getTime() < Date.now();
}

View File

@ -0,0 +1,18 @@
import { square } from "./index";
describe("square", () => {
it("returns the number pow 2", () => {
// Arrange
const num = 3;
Math.pow = jest.fn(); //.mockReturnValue(2);
// Act
square(num);
// Assert
expect(Math.pow).toHaveBeenCalledTimes(1);
expect(Math.pow).toHaveBeenCalledWith(3, 2);
// expect(square(num)).toBe(2);
});
});

View File

@ -0,0 +1,3 @@
export function square(value: number): number {
return Math.pow(value, 2);
}

View File

@ -0,0 +1,18 @@
import { toUpperCase } from "./index";
describe("toUpperCase", () => {
it("returns the string in uppercase", () => {
// Arrange
const input = "hello";
String.prototype.toUpperCase = jest.fn(); //.mockReturnValue("BLABLA");
// Act
toUpperCase(input);
// Assert
expect(input.toUpperCase).toHaveBeenCalledTimes(1);
expect(input.toUpperCase).toHaveBeenCalledWith();
// expect(toUpperCase(input)).toBe("BLABLA");
});
});

View File

@ -0,0 +1,3 @@
export function toUpperCase(value: string): string {
return value.toUpperCase();
}

View File

@ -1,4 +1,4 @@
import {multiply} from "./index";
import { multiply, multiplyArrays } from "./index";
describe("Test multiply", () => {
it.each([
@ -19,3 +19,16 @@ describe("Test multiply", () => {
);
});
describe('multiplyArrays', () => {
test('multiplie les éléments de deux tableaux de même taille', () => {
expect(multiplyArrays([3, 5, 2], [4, 3, 1])).toEqual([12, 15, 2]);
});
test('lève une exception si les tableaux ne sont pas de même taille', () => {
expect(() => multiplyArrays([1, 2, 3], [4, 5])).toThrowError('Les tableaux ne sont pas de même taille.');
});
test('lève une exception si les tableaux sont vides', () => {
expect(() => multiplyArrays([], [])).toThrowError('Les tableaux sont vides.');
});
});

View File

@ -1,11 +1,22 @@
async function start() {
console.log("Application starts...");
console.log("Application ends...");
}
start();
export function multiply (a : number, b : number) : number {
return a*b;
}
export function multiplyArrays(arr1: number[], arr2: number[]): number[] {
// Vérifier si les tableaux sont vides
if (arr1.length === 0 || arr2.length === 0) {
throw new Error("Les tableaux sont vides.");
}
// Vérifier si les tableaux ont la même taille
if (arr1.length !== arr2.length) {
throw new Error("Les tableaux ne sont pas de même taille.");
}
// Multiplier les éléments des tableaux
const result: number[] = [];
for (let i = 0; i < arr1.length; i++) {
result.push(arr1[i] * arr2[i]);
}
return result;
}

View File

@ -0,0 +1,47 @@
import { multiplyArrays } from "./index";
describe("multiplyArrays", () => {
it.each([
{
arr1: [1, 2, 3],
arr2: [4, 5, 6],
expected: [4, 10, 18],
},
{
arr1: [3, 2, 3],
arr2: [4, 5, 3],
expected: [12, 10, 9],
},
])("should multiply all numbers of 2 arrays", ({ arr1, arr2, expected }) => {
// Arrange
// Act
const result = multiplyArrays(arr1, arr2);
// Assert
expect(result).toStrictEqual(expected);
});
it("should throw when one array is empty", () => {
// Arrange
const arr1 = [1, 2, 3];
const arr2: number[] = [];
// Act
const act = () => multiplyArrays(arr1, arr2);
// Assert
expect(act).toThrow("Arrays must have at least one element");
});
it("should throw when arrays length is different", () => {
// Arrange
const arr1 = [1, 2, 3];
const arr2 = [4, 5];
// Act
const act = () => multiplyArrays(arr1, arr2);
// Assert
expect(act).toThrow("Arrays must have the same length");
});
});

View File

@ -0,0 +1,16 @@
export function multiplyArrays(a: number[], b: number[]): number[] {
if (a.length === 0 || b.length === 0) {
throw new Error("Arrays must have at least one element");
}
if (a.length !== b.length) {
throw new Error("Arrays must have the same length");
}
const output: number[] = new Array(a.length);
for (let i = 0; i < output.length; i++) {
output[i] = a[i] * b[i];
}
return output;
}

View File

@ -0,0 +1,44 @@
import { multiplyArrays } from "./index";
describe("multiplyArrays", () => {
it.each([
{ arr1: [1, 2, 3], arr2: [4, 5, 6], expected: [4, 10, 18] },
{ arr1: [-1, -2, -3], arr2: [4, -5, 6], expected: [-4, 10, -18] },
{
arr1: [-1.1, -2.1, -3.1],
arr2: [4, -5, 6],
expected: [-4.4, 10.5, -18.6],
},
])("should multiply two arrays", ({ arr1, arr2, expected }) => {
// arrange
// act
const result = multiplyArrays(arr1, arr2);
// assert
expect(result).toStrictEqual(expected);
});
it("should throw an error if arrays are not the same length", () => {
// arrange
const arr1 = [1, 2, 3];
const arr2 = [4, 5];
// act
const act = () => multiplyArrays(arr1, arr2);
// assert
expect(act).toThrow("Arrays must be the same length");
});
it("should throw an error if arrays are empty", () => {
// arrange
const arr1: number[] = [];
const arr2: number[] = [];
// act
const act = () => multiplyArrays(arr1, arr2);
// assert
expect(act).toThrow("Arrays must not be empty");
});
});

View File

@ -0,0 +1,10 @@
export function multiplyArrays(arr1: number[], arr2: number[]): number[] {
const isSameLength = arr1.length === arr2.length;
if (!isSameLength) throw new Error("Arrays must be the same length");
const isOneEmpty = arr1.length === 0 || arr2.length === 0;
if (isOneEmpty) throw new Error("Arrays must not be empty");
return arr1.map((num, index) => num * arr2[index]);
}

View File

@ -0,0 +1,14 @@
import { removeDuplicates } from "./index";
describe("removeDuplicates", () => {
it("should multiply all numbers of 2 arrays", () => {
// Arrange
const arr = [1, 2, 2, 2, 3, 3, 4];
// Act
const result = removeDuplicates(arr);
// Assert
expect(result).toStrictEqual([1, 2, 3, 4]);
});
});

View File

@ -0,0 +1,3 @@
export function removeDuplicates(a: number[]): number[] {
return Array.from(new Set(a));
}

View File

@ -0,0 +1,14 @@
import { removeDuplicates } from "./index";
describe("removeDuplicates", () => {
it("should remove duplicates from an array", () => {
// arrange
const arr = [1, 2, 2, 3, 4, 4, 5];
// act
const result = removeDuplicates(arr);
// assert
expect(result).toStrictEqual([1, 2, 3, 4, 5]);
});
});

View File

@ -0,0 +1,3 @@
export function removeDuplicates(arr: number[]): number[] {
return Array.from(new Set(arr));
}

View File

@ -0,0 +1,14 @@
import { throwAnException } from "./index";
describe("testAnException", () => {
it("should throw an exception", () => {
// Arrange
// Act
const act = () => {
throwAnException();
};
// Assert
expect(act).toThrow("I am an exception");
});
});

View File

@ -0,0 +1,3 @@
export function throwAnException(): void {
throw new Error("I am an exception");
}

View File

@ -0,0 +1,37 @@
import "reflect-metadata";
import { container } from "tsyringe";
import { AgeValidation } from "./index";
describe("AgeValidation", () => {
const ageValidation = container.resolve(AgeValidation);
describe("validateAge", () => {
it.each([
{ input: "1", expected: 1 },
{ input: "18", expected: 18 },
{ input: "100", expected: 100 },
])(
"should return a number when given a string if represents a valid age",
({ input, expected }) => {
// arrange
// act
const result = ageValidation.validateAge(input);
// assert
expect(result).toBe(expected);
}
);
it.each([{ input: "-2", expected: "Input must be a valid age" }])(
"should throw an error if input does not represent a valid age",
({ input, expected }) => {
// arrange
// act
const act = () => ageValidation.validateAge(input);
// assert
expect(act).toThrow(expected);
}
);
});
});

View File

@ -0,0 +1,18 @@
import { singleton } from "tsyringe";
import { NumberValidation } from "../number";
@singleton()
export class AgeValidation {
public constructor(private numberValidation: NumberValidation) {}
public validateAge(input: string) {
try {
let number: number = this.numberValidation.validateInteger(input);
number = this.numberValidation.validatePositive(input);
return number;
} catch (error) {
throw new Error("Input must be a valid age");
}
}
}

View File

@ -0,0 +1,109 @@
import "reflect-metadata"
import { container } from "tsyringe";
import { NumberValidation } from "./index";
describe("NumberValidation", () => {
const numberValidation = container.resolve(NumberValidation);
describe("validateNumber", () => {
it.each([
{ input: "0", expected: 0 },
{ input: "1", expected: 1 },
{ input: "-1", expected: -1 },
{ input: "1.67", expected: 1.67 },
{ input: "-1.67", expected: -1.67 },
{ input: "-1e7", expected: -1e7 },
])(
"should return a number when given a string if valid",
({ input, expected }) => {
// arrange
// act
const result = numberValidation.validateNumber(input);
// assert
expect(result).toBe(expected);
}
);
it("should throw an error if input is not a number", () => {
// arrange
const input = "a";
// act
const act = () => numberValidation.validateNumber(input);
// assert
expect(act).toThrow("Input must be a number");
});
});
describe("validateInteger", () => {
it.each([
{ input: "0", expected: 0 },
{ input: "1", expected: 1 },
{ input: "-1", expected: -1 },
{ input: "1e3", expected: 1e3 },
])(
"should return an integer when given a string if valid",
({ input, expected }) => {
// arrange
// act
const result = numberValidation.validateInteger(input);
// assert
expect(result).toBe(expected);
}
);
it.each([
{ input: "1.67", expected: "Input must be an integer" },
{ input: "-1.67", expected: "Input must be an integer" },
{ input: "1e-3", expected: "Input must be an integer" },
])(
"should throw an error if input is not an integer",
({ input, expected }) => {
// arrange
// act
const act = () => numberValidation.validateInteger(input);
// assert
expect(act).toThrow(expected);
}
);
});
describe("validatePositive", () => {
it.each([
{ input: "0", expected: 0 },
{ input: "1", expected: 1 },
{ input: "1.67", expected: 1.67 },
{ input: "1e3", expected: 1e3 },
])(
"should return a positive number when given a string if valid",
({ input, expected }) => {
// arrange
// act
const result = numberValidation.validatePositive(input);
// assert
expect(result).toBe(expected);
}
);
it.each([
{ input: "-1", expected: "Input must be positive" },
{ input: "-1.67", expected: "Input must be positive" },
{ input: "-1e3", expected: "Input must be positive" },
])(
"should throw an error if input is not positive",
({ input, expected }) => {
// arrange
// act
const act = () => numberValidation.validatePositive(input);
// assert
expect(act).toThrow(expected);
}
);
});
});

View File

@ -0,0 +1,34 @@
import { singleton } from "tsyringe";
@singleton()
export class NumberValidation {
public validateNumber(input: string): number {
const number = Number(input);
if (isNaN(number)) {
throw new Error("Input must be a number");
}
return number;
}
public validateInteger(input: string): number {
const number = this.validateNumber(input);
if (!Number.isInteger(number)) {
throw new Error("Input must be an integer");
}
return number;
}
public validatePositive(input: string): number {
const number = this.validateNumber(input);
if (number < 0) {
throw new Error("Input must be positive");
}
return number;
}
}

View File

@ -0,0 +1,31 @@
import {hexToRgb} from "./index"
describe("hexToRgb", () => {
it.each([
{ hex: '#BD3F0A', expected: 'rgb(189,63,10)' },
{ hex: '#A3BF7E', expected: 'rgb(163,191,126)' },
])(
"should convert $hex to $expected",
({ hex, expected }: { hex: string, expected: string }) => {
// act
const result = hexToRgb(hex);
// assert
expect(result).toEqual(expected);
console.log(`Test with hex = ${hex}, expected = ${expected}, result = ${result}`);
}
);
it.each([
{ hex: '', expectedErrorMsg: "Couleur hexadécimale invalide, ne doit pas être vide" },
{ hex: 'BD3F0A', expectedErrorMsg: "Couleur hexadécimale invalide, doit commencer par #" },
{ hex: '#', expectedErrorMsg: "Couleur hexadécimale invalide, doit contenir 6 caractères" },
{ hex: '#12345', expectedErrorMsg: "Couleur hexadécimale invalide, doit contenir 6 caractères" },
{ hex: '#GHIJKL', expectedErrorMsg: "Couleur hexadécimale invalide, caractères invalides" },
])(
"should throw an error for invalid hex $hex",
({ hex, expectedErrorMsg }: { hex: string, expectedErrorMsg: string }) => {
// assert
expect(() => hexToRgb(hex)).toThrow(expectedErrorMsg);
}
);
});

View File

@ -0,0 +1,28 @@
import {parse} from "../hexToDecimal"
export function hexToRgb(hex: string): string {
if (hex === "") {
throw new Error("Couleur hexadécimale invalide, ne doit pas être vide");
}
if (!hex.startsWith("#")) {
throw new Error("Couleur hexadécimale invalide, doit commencer par #");
}
hex = hex.slice(1);
if (hex.length !== 6) {
throw new Error("Couleur hexadécimale invalide, doit contenir 6 caractères");
}
if (!/^[0-9A-F]{6}$/.test(hex.toUpperCase())) {
throw new Error("Couleur hexadécimale invalide, caractères invalides");
}
const r: number = parse(hex.slice(0, 2));
const g: number = parse(hex.slice(2, 4));
const b: number = parse(hex.slice(4, 6));
return `rgb(${r},${g},${b})`;
}

View File

@ -0,0 +1,35 @@
import {parse} from "./index"
describe("parse", () => {
it.each([
{a: 'CE', expected: 206},
{a: '9B', expected: 155},
{a: 'E6', expected: 230},
{a: '25', expected: 37},
])(
"should return conversion of $a hex value to decimal value",
({a, expected}: { a: string, expected: number }) => {
// act
const result = parse(a);
// assert
expect(result).toEqual(expected);
console.log(`Test with a = ${a}, expected = ${expected}, result = ${result}`);
}
);
it("should throw an error for empty string", () => {
expect(() => parse("")).toThrow("Teinte hexadécimale invalide, teinte vide");
});
it("should throw an error for invalid length", () => {
expect(() => parse("B")).toThrow("Teinte hexadécimale invalide, la teinte doit contenir 2 caractères");
expect(() => parse("2BC")).toThrow("Teinte hexadécimale invalide, la teinte doit contenir 2 caractères");
});
it("should throw an error for invalid characters", () => {
expect(() => parse("-G")).toThrow("Teinte hexadécimale invalide, caractère non valide");
expect(() => parse("1.")).toThrow("Teinte hexadécimale invalide, caractère non valide");
expect(() => parse("G0")).toThrow("Teinte hexadécimale invalide, caractère non valide");
expect(() => parse("0G")).toThrow("Teinte hexadécimale invalide, caractère non valide");
});
});

View File

@ -0,0 +1,22 @@
export function parse(a: string): number {
const alphabet: string = "0123456789ABCDEF";
if (a === "") {
throw new Error("Teinte hexadécimale invalide, teinte vide");
}
if (a.length !== 2) {
throw new Error("Teinte hexadécimale invalide, la teinte doit contenir 2 caractères");
}
const hexToDecimal = (char: string): number => {
const value = alphabet.indexOf(char.toUpperCase());
if (value == -1) {
throw new Error(" Teinte hexadécimale invalide, caractère non valide");
} else {
return value;
}
};
return hexToDecimal(a[0]) * 16 + hexToDecimal(a[1]);
}