Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions apps/frontend/src/components/tee/SignatureTool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ export default function SignatureTool({
const [signingFace, setSigningFace] = useState<'front' | 'back'>('back');

const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [originalSize, setOriginalSize] = useState<number>(0);
const [previewUrl, setPreviewUrl] = useState<string | null>(null);

useEffect(() => {
Expand Down Expand Up @@ -326,9 +325,6 @@ export default function SignatureTool({

const finishDraw = () => {
const dataUrl = canvasRef.current!.toDataURL('image/png');
const base64Str = dataUrl.split(',')[1];
const originalBytesSize = base64Str ? Math.floor(base64Str.length * 0.75) : 0;
setOriginalSize(originalBytesSize);

const defaultX = signingFace === 'front' ? 0.3 : 0.7;
setPendingSig({ id: `tmp-${Date.now()}`, dataUrl, face: signingFace, x: defaultX, y: 0.55, scale: 0.6, rotation: 0 });
Expand All @@ -352,7 +348,6 @@ export default function SignatureTool({

setError(null);
setSelectedFile(file);
setOriginalSize(file.size);
return true;
};

Expand Down Expand Up @@ -381,14 +376,6 @@ export default function SignatureTool({
setPhase('submitting');
try {
const signatureBlob = dataURLtoBlob(pendingSig.dataUrl);
const payloadSize = signatureBlob.size;
const contentType = 'multipart/form-data';

console.log('Original file size:', originalSize);
console.log('Payload size:', payloadSize);
console.log('Content-Type:', contentType);
console.log('Content-Length:', payloadSize);

const formData = new FormData();
formData.append('signerName', signerName.trim());
formData.append('face', pendingSig.face ?? 'back');
Expand Down
86 changes: 86 additions & 0 deletions apps/frontend/src/components/tee/__tests__/SignatureTool.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import React from 'react';

vi.mock('framer-motion', () => ({
AnimatePresence: ({ children }: { children: React.ReactNode }) => children,
motion: {
div: ({ children, ...props }: { children: React.ReactNode }) => (
<div {...(props as Record<string, unknown>)}>{children}</div>
),
},
}));

vi.mock('../../../utils/sigRemover', () => ({
removeSignatureBackground: vi.fn().mockResolvedValue('data:image/png;base64,c2lnbmF0dXJl'),
}));

vi.mock('../PremiumTee', () => ({
default: () => <div data-testid="premium-tee" />,
}));

vi.mock('../../../utils/api', () => ({
default: {
post: vi.fn(),
},
}));

import api from '../../../utils/api';
import SignatureTool from '../SignatureTool';

const mockApi = api as unknown as {
post: ReturnType<typeof vi.fn>;
};

describe('SignatureTool', () => {
it('submits an uploaded signature and reports the saved overlay', async () => {
const onSigned = vi.fn();
mockApi.post.mockResolvedValue({
data: {
signature: {
id: 'signature-1',
signerDataUrl: 'data:image/png;base64,c2F2ZWQ=',
face: 'back',
x: 0.7,
y: 0.55,
scale: 0.6,
rotation: 0,
},
},
});

const { container } = render(
<SignatureTool
shareId="share-1"
shirtColor="navy"
textColor="cream"
nameOnBack="Test Tee"
existingSignatures={[]}
defaultSignerName="Test Signer"
onCancel={vi.fn()}
onSigned={onSigned}
/>,
);

fireEvent.click(screen.getByRole('button', { name: /upload/i }));
const fileInput = container.querySelector<HTMLInputElement>('input[type="file"]');
expect(fileInput).not.toBeNull();
fireEvent.change(fileInput!, {
target: { files: [new File(['signature'], 'signature.png', { type: 'image/png' })] },
});
fireEvent.click(screen.getByRole('button', { name: 'Use this signature →' }));

await screen.findByRole('button', { name: 'Save signature' });
fireEvent.click(screen.getByRole('button', { name: 'Save signature' }));

await waitFor(() => expect(mockApi.post).toHaveBeenCalledWith(
'/tee/share/share-1/sign',
expect.any(FormData),
{ headers: { 'Content-Type': 'multipart/form-data' } },
));
await waitFor(() => expect(onSigned).toHaveBeenCalledWith(expect.objectContaining({
id: 'signature-1',
dataUrl: 'data:image/png;base64,c2F2ZWQ=',
})));
});
});
6 changes: 5 additions & 1 deletion apps/frontend/src/test/setup.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
import '@testing-library/jest-dom';
import '@testing-library/jest-dom';
import { vi } from 'vitest';

URL.createObjectURL = vi.fn(() => 'blob:signature-preview');
URL.revokeObjectURL = vi.fn();