diff --git a/src/js/logic/add-watermark.ts b/src/js/logic/add-watermark.ts index 537e368..61d5a20 100644 --- a/src/js/logic/add-watermark.ts +++ b/src/js/logic/add-watermark.ts @@ -4,7 +4,7 @@ import { readFileAsArrayBuffer, hexToRgb, } from '../utils/helpers.js'; -import { state } from '../state.js'; +import { state, resetState } from '../state.js'; import { PDFDocument as PDFLibDocument, @@ -175,6 +175,15 @@ export async function addWatermark() { new Blob([newPdfBytes], { type: 'application/pdf' }), 'watermarked.pdf' ); + + const toolid = state.activeTool; + resetState(); + if (toolid) { + const element = document.querySelector( + `[data-tool-id="${toolid}"]` + ) as HTMLElement; + if (element) element.click(); + } } catch (e) { console.error(e); showAlert( diff --git a/src/tests/watermark.test.ts b/src/tests/watermark.test.ts new file mode 100644 index 0000000..8100760 --- /dev/null +++ b/src/tests/watermark.test.ts @@ -0,0 +1,227 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import { state, resetState } from '../js/state'; + +describe('Watermark Feature', () => { + beforeEach(() => { + document.body.innerHTML = ` + + + + + + +
+ + + +
+ + + +
+ `; + + state.activeTool = 'add-watermark'; + state.files = []; + state.pdfDoc = null; + state.pdfPages = []; + state.currentPdfUrl = null; + }); + + describe('resetState', () => { + it('should clear watermark text input after reset', () => { + const watermarkText = document.getElementById( + 'watermark-text' + ) as HTMLInputElement; + watermarkText.value = 'CONFIDENTIAL'; + + resetState(); + + expect(state.activeTool).toBe(null); + expect(state.files).toEqual([]); + expect(state.pdfDoc).toBe(null); + expect(state.pdfPages).toEqual([]); + expect(state.currentPdfUrl).toBe(null); + }); + + it('should reset state files array', () => { + state.files = [new File(['content'], 'test.pdf')]; + + resetState(); + + expect(state.files).toEqual([]); + }); + + it('should reset activeTool to null', () => { + state.activeTool = 'add-watermark'; + + resetState(); + + expect(state.activeTool).toBe(null); + }); + + it('should reset pdfDoc to null', () => { + state.pdfDoc = {} as any; + + resetState(); + + expect(state.pdfDoc).toBe(null); + }); + + it('should reset pdfPages array', () => { + state.pdfPages = [1, 2, 3] as any; + + resetState(); + + expect(state.pdfPages).toEqual([]); + }); + + it('should reset currentPdfUrl to null', () => { + state.currentPdfUrl = 'blob:http://example.com/123'; + + resetState(); + + expect(state.currentPdfUrl).toBe(null); + }); + + it('should clear tool-content innerHTML', () => { + const toolContent = document.getElementById('tool-content'); + if (toolContent) toolContent.innerHTML = '
Some content
'; + + resetState(); + + expect(toolContent?.innerHTML).toBe(''); + }); + }); + + describe('Watermark Type Toggle', () => { + it('should show text options by default', () => { + const textOptions = document.getElementById('text-watermark-options'); + const imageOptions = document.getElementById('image-watermark-options'); + + expect(imageOptions?.classList.contains('hidden')).toBe(true); + expect(textOptions?.classList.contains('hidden')).toBe(false); + }); + + it('should have text radio checked by default', () => { + const textRadio = document.querySelector( + 'input[name="watermark-type"][value="text"]' + ) as HTMLInputElement; + const imageRadio = document.querySelector( + 'input[name="watermark-type"][value="image"]' + ) as HTMLInputElement; + + expect(textRadio.checked).toBe(true); + expect(imageRadio.checked).toBe(false); + }); + }); + + describe('Watermark Input Validation', () => { + it('should accept valid font size', () => { + const fontSize = document.getElementById('font-size') as HTMLInputElement; + fontSize.value = '48'; + + expect(parseInt(fontSize.value)).toBeGreaterThan(0); + expect(parseInt(fontSize.value)).toBeLessThanOrEqual(200); + }); + + it('should have default font size of 72', () => { + const fontSize = document.getElementById('font-size') as HTMLInputElement; + + expect(parseInt(fontSize.value)).toBe(72); + }); + + it('should accept valid opacity range', () => { + const opacity = document.getElementById( + 'opacity-text' + ) as HTMLInputElement; + opacity.value = '0.5'; + + const opacityValue = parseFloat(opacity.value); + expect(opacityValue).toBeGreaterThanOrEqual(0); + expect(opacityValue).toBeLessThanOrEqual(1); + }); + + it('should have default opacity of 0.3', () => { + const opacity = document.getElementById( + 'opacity-text' + ) as HTMLInputElement; + + expect(parseFloat(opacity.value)).toBe(0.3); + }); + + it('should accept valid angle range', () => { + const angle = document.getElementById('angle-text') as HTMLInputElement; + angle.value = '45'; + + const angleValue = parseInt(angle.value); + expect(angleValue).toBeGreaterThanOrEqual(-180); + expect(angleValue).toBeLessThanOrEqual(180); + }); + + it('should have default angle of 0', () => { + const angle = document.getElementById('angle-text') as HTMLInputElement; + + expect(parseInt(angle.value)).toBe(0); + }); + + it('should accept valid hex color', () => { + const textColor = document.getElementById( + 'text-color' + ) as HTMLInputElement; + textColor.value = '#FF5733'; + + expect(textColor.value).toMatch(/^#[0-9A-F]{6}$/i); + }); + + it('should have default color of black', () => { + const textColor = document.getElementById( + 'text-color' + ) as HTMLInputElement; + + expect(textColor.value).toBe('#000000'); + }); + }); + + describe('State Management', () => { + it('should maintain activeTool as add-watermark', () => { + expect(state.activeTool).toBe('add-watermark'); + }); + + it('should start with empty files array', () => { + expect(state.files).toEqual([]); + }); + + it('should allow adding files to state', () => { + const file = new File(['content'], 'test.pdf', { + type: 'application/pdf', + }); + state.files.push(file); + + expect(state.files.length).toBe(1); + expect(state.files[0].name).toBe('test.pdf'); + }); + }); + + describe('UI Elements State', () => { + it('should have process button disabled by default', () => { + const processBtn = document.getElementById( + 'process-btn' + ) as HTMLButtonElement; + + expect(processBtn.disabled).toBe(true); + }); + + it('should have file controls hidden by default', () => { + const fileControls = document.getElementById('file-controls'); + + expect(fileControls?.classList.contains('hidden')).toBe(true); + }); + + it('should have image watermark options hidden by default', () => { + const imageOptions = document.getElementById('image-watermark-options'); + + expect(imageOptions?.classList.contains('hidden')).toBe(true); + }); + }); +});