Skip to content
This repository has been archived by the owner on Jun 25, 2024. It is now read-only.

Commit

Permalink
✅ Add tests for the color functionillity
Browse files Browse the repository at this point in the history
🏷️ Enhance typping
🥅 Make the code more robust to incorrect input
  • Loading branch information
Dlurak committed Oct 28, 2023
1 parent 5c3ddd6 commit a8aa5c6
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 28 deletions.
1 change: 0 additions & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ export default defineConfig({
/* Run your local dev server before starting the tests */
webServer: {
command: 'pnpm build && pnpm preview --port 4173 --host 127.0.0.1',
// command: 'echo "Temporarily disabled"',
url: 'http://127.0.0.1:4173/',
reuseExistingServer: !process.env.CI,
timeout: 1000 * 60 * 5
Expand Down
8 changes: 4 additions & 4 deletions src/lib/colors/ColorPicker.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import I18n from '$lib/I18n.svelte';
import Modal from '$lib/Modal.svelte';
import SubmitButton from '$lib/SubmitButton.svelte';
import type { IntRange } from '../../types/utils';
import type { RangeRGB } from '../../types/subjectColors';
import { rgbToHex } from './hexToRgb';
export let r: IntRange<0, 255> = 0;
export let g: IntRange<0, 255> = 0;
export let b: IntRange<0, 255> = 0;
export let r: RangeRGB = 0;
export let g: RangeRGB = 0;
export let b: RangeRGB = 0;
export let open = false;
Expand Down
35 changes: 18 additions & 17 deletions src/lib/colors/hexToRgb.ts
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)}`;
};
2 changes: 1 addition & 1 deletion src/types/subjectColors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { IntRange } from './utils';

type RangeRGB = IntRange<0, 255>;
export type RangeRGB = IntRange<0, 256>;

export type RGB = {
r: RangeRGB;
Expand Down
12 changes: 7 additions & 5 deletions src/zod/subjectColor.ts
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
});
100 changes: 100 additions & 0 deletions tests/colors.test.ts
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();
}
});
});

0 comments on commit a8aa5c6

Please sign in to comment.