add e2e tests

This commit is contained in:
Habib
2024-06-28 14:26:33 +02:00
parent 3b575af888
commit eaea6f5858
8 changed files with 973 additions and 16 deletions

889
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -36,6 +36,7 @@
"@types/omggif": "^1.0.5", "@types/omggif": "^1.0.5",
"color": "^4.2.3", "color": "^4.2.3",
"formik": "^2.4.6", "formik": "^2.4.6",
"jimp": "^0.22.12",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"morsee": "^1.0.9", "morsee": "^1.0.9",
"notistack": "^3.0.1", "notistack": "^3.0.1",

View File

@@ -1,5 +1,5 @@
import React, { ChangeEvent, useRef, useState } from 'react'; import React, { ChangeEvent, useRef, useState } from 'react';
import { Box, Stack, TextField } from '@mui/material'; import { Box, Stack, TextField, TextFieldProps } from '@mui/material';
import PaletteIcon from '@mui/icons-material/Palette'; import PaletteIcon from '@mui/icons-material/Palette';
import IconButton from '@mui/material/IconButton'; import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
@@ -7,14 +7,15 @@ import { globalDescriptionFontSize } from '../../config/uiConfig';
interface ColorSelectorProps { interface ColorSelectorProps {
value: string; value: string;
onChange: (val: string) => void; onColorChange: (val: string) => void;
description: string; description: string;
} }
const ColorSelector: React.FC<ColorSelectorProps> = ({ const ColorSelector: React.FC<ColorSelectorProps & TextFieldProps> = ({
value = '#ffffff', value = '#ffffff',
onChange, onColorChange,
description description,
...props
}) => { }) => {
const [color, setColor] = useState<string>(value); const [color, setColor] = useState<string>(value);
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
@@ -22,7 +23,7 @@ const ColorSelector: React.FC<ColorSelectorProps> = ({
const handleColorChange = (event: ChangeEvent<HTMLInputElement>) => { const handleColorChange = (event: ChangeEvent<HTMLInputElement>) => {
const val = event.target.value; const val = event.target.value;
setColor(val); setColor(val);
onChange(val); onColorChange(val);
}; };
return ( return (
@@ -32,6 +33,7 @@ const ColorSelector: React.FC<ColorSelectorProps> = ({
sx={{ backgroundColor: 'white' }} sx={{ backgroundColor: 'white' }}
value={color} value={color}
onChange={handleColorChange} onChange={handleColorChange}
{...props}
/> />
<IconButton onClick={() => inputRef.current?.click()}> <IconButton onClick={() => inputRef.current?.click()}>
<PaletteIcon /> <PaletteIcon />

View File

@@ -125,12 +125,12 @@ export default function ChangeColorsInPng() {
<Box> <Box>
<ColorSelector <ColorSelector
value={values.fromColor} value={values.fromColor}
onChange={(val) => updateField('fromColor', val)} onColorChange={(val) => updateField('fromColor', val)}
description={'Replace this color (from color)'} description={'Replace this color (from color)'}
/> />
<ColorSelector <ColorSelector
value={values.toColor} value={values.toColor}
onChange={(val) => updateField('toColor', val)} onColorChange={(val) => updateField('toColor', val)}
description={'With this color (to color)'} description={'With this color (to color)'}
/> />
<TextFieldWithDesc <TextFieldWithDesc

View File

@@ -0,0 +1,72 @@
import { expect, test } from '@playwright/test';
import { Buffer } from 'buffer';
import path from 'path';
import Jimp from 'jimp';
test.describe('Convert JPG to PNG tool', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/png/convert-jgp-to-png');
});
test('should convert jpg to png', async ({ page }) => {
// Upload image
const fileInput = page.locator('input[type="file"]');
const imagePath = path.join(__dirname, 'test.jpg');
await fileInput?.setInputFiles(imagePath);
// Click on download
const downloadPromise = page.waitForEvent('download');
await page.getByText('Save as').click();
// Intercept and read downloaded PNG
const download = await downloadPromise;
const downloadStream = await download.createReadStream();
const chunks = [];
for await (const chunk of downloadStream) {
chunks.push(chunk);
}
const fileContent = Buffer.concat(chunks);
expect(fileContent.length).toBeGreaterThan(0);
// Check that the first pixel is 0x808080ff
const image = await Jimp.read(fileContent);
const color = image.getPixelColor(0, 0);
expect(color).toBe(0x808080ff);
});
test('should apply transparency before converting jpg to png', async ({
page
}) => {
// Upload image
const fileInput = page.locator('input[type="file"]');
const imagePath = path.join(__dirname, 'test.jpg');
await fileInput?.setInputFiles(imagePath);
// Enable transparency on color 0x808080
await page.getByLabel('Enable PNG Transparency').check();
await page.getByTestId('color-input').fill('#808080');
// Click on download
const downloadPromise = page.waitForEvent('download');
await page.getByText('Save as').click();
// Intercept and read downloaded PNG
const download = await downloadPromise;
const downloadStream = await download.createReadStream();
const chunks = [];
for await (const chunk of downloadStream) {
chunks.push(chunk);
}
const fileContent = Buffer.concat(chunks);
expect(fileContent.length).toBeGreaterThan(0);
// Check that the first pixel is transparent
const image = await Jimp.read(fileContent);
const color = image.getPixelColor(0, 0);
expect(color).toBe(0);
});
});

View File

@@ -133,20 +133,21 @@ export default function ConvertJgpToPng() {
compute={compute} compute={compute}
getGroups={({ values, updateField }) => [ getGroups={({ values, updateField }) => [
{ {
title: 'From color and to color', title: 'PNG Transparency Color',
component: ( component: (
<Box> <Box>
<CheckboxWithDesc <CheckboxWithDesc
key="enableTransparency" key="enableTransparency"
title="PNG Transparency Color" title="Enable PNG Transparency"
checked={!!values.enableTransparency} checked={!!values.enableTransparency}
onChange={(value) => updateField('enableTransparency', value)} onChange={(value) => updateField('enableTransparency', value)}
description="Make the color below transparent." description="Make the color below transparent."
/> />
<ColorSelector <ColorSelector
value={values.color} value={values.color}
onChange={(val) => updateField('color', val)} onColorChange={(val) => updateField('color', val)}
description={'With this color (to color)'} description={'With this color (to color)'}
inputProps={{ 'data-testid': 'color-input' }}
/> />
<TextFieldWithDesc <TextFieldWithDesc
value={values.similarity} value={values.similarity}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -118,7 +118,7 @@ export default function ChangeColorsInPng() {
<Box> <Box>
<ColorSelector <ColorSelector
value={values.fromColor} value={values.fromColor}
onChange={(val) => updateField('fromColor', val)} onColorChange={(val) => updateField('fromColor', val)}
description={'Replace this color (from color)'} description={'Replace this color (from color)'}
/> />
<TextFieldWithDesc <TextFieldWithDesc