This repository has been archived by the owner on Jun 25, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✅ Add tests for the color functionillity
🏷️ Enhance typping 🥅 Make the code more robust to incorrect input
- Loading branch information
Showing
6 changed files
with
130 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,22 @@ | ||
import type { IntRange } from '../../types/utils'; | ||
import type { RGB, RangeRGB } from '../../types/subjectColors'; | ||
import { rgbSchema } from '../../zod/subjectColor'; | ||
|
||
type Range = IntRange<0, 255>; | ||
export const hexToRgb = (hex: string): RGB | null => { | ||
if (!/^#[0-9a-f]{6}$/i.test(hex)) { | ||
return null; | ||
} | ||
return { | ||
r: parseInt(hex.slice(1, 3), 16) as RangeRGB, | ||
g: parseInt(hex.slice(3, 5), 16) as RangeRGB, | ||
b: parseInt(hex.slice(5, 7), 16) as RangeRGB | ||
}; | ||
}; | ||
|
||
export const hexToRgb = ( | ||
hex: string | ||
): { | ||
r: Range; | ||
g: Range; | ||
b: Range; | ||
} => ({ | ||
r: parseInt(hex.slice(1, 3), 16) as Range, | ||
g: parseInt(hex.slice(3, 5), 16) as Range, | ||
b: parseInt(hex.slice(5, 7), 16) as Range | ||
}); | ||
|
||
// create a function to make any decimal number a hex number with 2 digits | ||
const makeHex = (n: number): string => n.toString(16).padStart(2, '0'); | ||
|
||
export const rgbToHex = (r: Range, g: Range, b: Range): string => | ||
`#${makeHex(r)}${makeHex(g)}${makeHex(b)}`; | ||
export const rgbToHex = (r: RangeRGB, g: RangeRGB, b: RangeRGB): string | null => { | ||
const result = rgbSchema.safeParse({ r, g, b }); | ||
if (!result.success) return null; | ||
|
||
return `#${makeHex(r)}${makeHex(g)}${makeHex(b)}`; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
import { z } from 'zod'; | ||
|
||
export const rgbSchema = z.object({ | ||
r: z.number().max(255).min(0), | ||
g: z.number().max(255).min(0), | ||
b: z.number().max(255).min(0) | ||
}); | ||
|
||
export const subjectColorSchema = z.object({ | ||
subject: z.string(), | ||
color: z.object({ | ||
r: z.number().max(255).min(0), | ||
g: z.number().max(255).min(0), | ||
b: z.number().max(255).min(0) | ||
}) | ||
color: rgbSchema | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// import { hexToRgb } from '$lib/colors/hexToRgb'; | ||
import { test, expect } from '@playwright/test'; | ||
import { hexToRgb, rgbToHex } from '../src/lib/colors/hexToRgb'; | ||
|
||
test.describe('hexToRgb', () => { | ||
test('it should convert correctly to rgb', () => { | ||
expect(hexToRgb('#000000')).toEqual({ r: 0, g: 0, b: 0 }); | ||
expect(hexToRgb('#ffffff')).toEqual({ r: 255, g: 255, b: 255 }); | ||
expect(hexToRgb('#ff00ff')).toEqual({ r: 255, g: 0, b: 255 }); | ||
expect(hexToRgb('#4488ff')).toEqual({ r: 68, g: 136, b: 255 }); | ||
expect(hexToRgb('#1ab2cd')).toEqual({ r: 26, g: 178, b: 205 }); | ||
expect(hexToRgb('#7f7f7f')).toEqual({ r: 127, g: 127, b: 127 }); | ||
expect(hexToRgb('#0088cc')).toEqual({ r: 0, g: 136, b: 204 }); | ||
expect(hexToRgb('#ffcc00')).toEqual({ r: 255, g: 204, b: 0 }); | ||
expect(hexToRgb('#9900cc')).toEqual({ r: 153, g: 0, b: 204 }); | ||
}); | ||
test("it shouldn't work", () => { | ||
expect(hexToRgb('Hi there')).toEqual(null); | ||
expect(hexToRgb('')).toEqual(null); | ||
expect(hexToRgb('#')).toEqual(null); | ||
expect(hexToRgb('#00000')).toEqual(null); | ||
expect(hexToRgb('#gghh00')).toEqual(null); | ||
expect(hexToRgb('#fffff-')).toEqual(null); | ||
}); | ||
}); | ||
|
||
test.describe('rgbToHex', () => { | ||
test('it works', () => { | ||
expect(rgbToHex(0, 0, 0)).toEqual('#000000'); | ||
expect(rgbToHex(255, 255, 255)).toEqual('#ffffff'); | ||
expect(rgbToHex(255, 0, 255)).toEqual('#ff00ff'); | ||
expect(rgbToHex(42, 42, 42)).toEqual('#2a2a2a'); | ||
}); | ||
}); | ||
|
||
// now real e2e tests | ||
test.describe('the colors page', () => { | ||
test('it should work', async ({ page }) => { | ||
await page.goto('/'); | ||
|
||
await page.getByRole('link', { name: 'Einstellungen ' }).click(); | ||
await page.getByRole('link', { name: ' Farben' }).click(); | ||
|
||
await expect(page).toHaveTitle('Dlool | Farben für Fächer'); | ||
|
||
await page.getByRole('button', { name: ' Neues Fach hinzufügen' }).click(); | ||
|
||
await page.getByPlaceholder('Fach').click(); | ||
await page.getByPlaceholder('Fach').fill('Blau'); | ||
await page.getByRole('button', { name: '#3f51b5' }).click(); | ||
|
||
const sliderLoc = await page.getByRole('slider'); | ||
await expect(await sliderLoc.count()).toEqual(3); | ||
|
||
// set the first two sliders to 0 | ||
await sliderLoc.first().evaluate((el: HTMLInputElement) => (el.value = '0')); | ||
await sliderLoc.nth(1).evaluate((el: HTMLInputElement) => (el.value = '0')); | ||
await sliderLoc.nth(2).evaluate((el: HTMLInputElement) => (el.value = '255')); | ||
(await sliderLoc.all()).forEach(async (el) => { | ||
await el.dispatchEvent('input'); | ||
await el.dispatchEvent('change'); | ||
}); | ||
|
||
const previewArea = await page.locator( | ||
'.p-4 > .bg-\\[rgb\\(var\\(--red\\)\\,var\\(--green\\)\\,var\\(--blue\\)\\)\\]' | ||
); | ||
const bgValue = await previewArea.evaluate( | ||
(el: HTMLDivElement) => window.getComputedStyle(el).backgroundColor | ||
); | ||
await expect(bgValue).toEqual('rgb(0, 0, 255)'); | ||
await page.getByRole('button', { name: 'Farbe auswählen' }).click(); | ||
}); | ||
|
||
test('it should be stored on reload', async ({ page }) => { | ||
await page.goto('/settings/colors'); | ||
await expect(page).toHaveTitle('Dlool | Farben für Fächer'); | ||
|
||
await page.getByRole('button', { name: ' Neues Fach hinzufügen' }).click(); | ||
// now fill in the subject | ||
await page.getByPlaceholder('Fach').click(); | ||
await page.getByPlaceholder('Fach').fill('Playwright'); | ||
await page.getByRole('button', { name: '#3f51b5' }).click(); | ||
const sliderList = await page.getByRole('slider').all(); | ||
|
||
for (const el of sliderList) { | ||
await el.evaluate((el: HTMLInputElement) => (el.value = '0')); | ||
await el.dispatchEvent('input'); | ||
await el.dispatchEvent('change'); | ||
} | ||
|
||
await page.getByRole('button', { name: 'Farbe auswählen' }).click(); | ||
|
||
// run two times | ||
for (let i = 0; i < 2; i++) { | ||
await expect(await page.getByRole('button', { name: '#000000' })).toBeVisible(); | ||
await expect(await page.getByPlaceholder('Fach')).toHaveValue('Playwright'); | ||
await page.reload(); | ||
} | ||
}); | ||
}); |