34import * as
fs from
'fs/promises';
35import * as
path from
'path';
36import * as
os from
'os';
37import { Watermark,
watermark } from
'../modules/watermark';
56 private _html:
string =
'';
57 private messageHandlers: Array<(message: any) =>
void> = [];
71 set html(value:
string) {
81 this.messageHandlers.push(handler);
82 return { dispose: () => { } };
90 this.messageHandlers.forEach(handler => handler(message));
115 public viewType:
string,
116 public title:
string,
117 public showOptions:
vscode.ViewColumn,
118 public options:
vscode.WebviewPanelOptions &
vscode.WebviewOptions
128suite(
'Watermark Test Suite', () => {
132 let originalCreateWebviewPanel: typeof
vscode.window.createWebviewPanel;
143 tempDir = await
fs.mkdtemp(
path.join(
os.tmpdir(),
'watermark-test-'));
144 testFilePath =
path.join(tempDir,
'test-watermarks.json');
150 " _ _____ _ ____ ___ _ _ _____ _____ _____ _ _ _ _____ ____",
151 "/ \\ /|/ __// \\ /|/ __\\\\ \\// / \\ / __//__ __Y __// \\ / \\ / \\/ __// __\\",
152 "| |_||| \\ | |\\ ||| \\/| \\ / | | | \\ / \\ | \\ | | | | | || \\ | \\/|",
153 "| | ||| /_ | | \\||| / / / | |_/\\| /_ | | | /_ | |_/\\| |_/\\| || /_ | /",
154 "\\_/ \\|\\____\\\\_/ \\|\\_/\\_\\/_/ \\____/\\____\\ \\_/ \\____\\\\____/\\____/\\_/\\____\\\\_/\\_\\",
162 " | | | | | | | | | | (_)",
163 " | |__| | ___ _ __ _ __ _ _ | | ___| |_ ___| | |_ ___ _ __",
164 " | __ |/ _ \\ '_ \\| '__| | | | | | / _ \\ __/ _ \\ | | |/ _ \\ '__|",
165 " | | | | __/ | | | | | |_| | | |___| __/ || __/ | | | __/ |",
166 " |_| |_|\\___|_| |_|_| \\__, | |______\\___|\\__\\___|_|_|_|\\___|_|",
174 " _ _ ____ _ _ ____ _ _ __ ____ ____ ____ __ __ ____ ____ ____",
175 "( )_( )( ___)( \\( )( _ \\( \\/ ) ( ) ( ___)(_ _)( ___)( ) ( ) (_ _)( ___)( _ \\",
176 " ) _ ( )__) ) ( ) / \\ / )(__ )__) )( )__) )(__ )(__ _)(_ )__) ) /",
177 "(_) (_)(____)(_)\\_)(_)\\_) (__) (____)(____) (__) (____)(____)(____)(____)(____)(_)\\_)"
183 "╦ ╦┌─┐┌┐┌┬─┐┬ ┬ ╦ ┌─┐┌┬┐┌─┐┬ ┬ ┬┌─┐┬─┐",
184 "╠═╣├┤ │││├┬┘└┬┘ ║ ├┤ │ ├┤ │ │ │├┤ ├┬┘",
185 "╩ ╩└─┘┘└┘┴└─ ┴ ╩═╝└─┘ ┴ └─┘┴─┘┴─┘┴└─┘┴└─"
191 "██ ██ ███████ ███ ██ ██████ ██ ██ ██ ███████ ████████ ███████ ██ ██ ██ ███████ ██████",
192 "██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██",
193 "███████ █████ ██ ██ ██ ██████ ████ ██ █████ ██ █████ ██ ██ ██ █████ ██████",
194 "██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██",
195 "██ ██ ███████ ██ ████ ██ ██ ██ ███████ ███████ ██ ███████ ███████ ███████ ██ ███████ ██ ██"
203 originalCreateWebviewPanel =
vscode.window.createWebviewPanel;
204 vscode.window.createWebviewPanel = (
207 showOptions:
vscode.ViewColumn | { readonly viewColumn:
vscode.ViewColumn; readonly preserveFocus?:
boolean | undefined; },
208 options?:
vscode.WebviewPanelOptions &
vscode.WebviewOptions
210 const column = typeof showOptions ===
'object' ? showOptions.viewColumn : showOptions;
211 const opts = options || {};
213 lastCreatedWebview = lastCreatedPanel.webview;
216 Object.defineProperty(lastCreatedWebview,
'html', {
217 get: () => capturedHtml,
219 capturedHtml = value;
223 return lastCreatedPanel as any;
231 teardown(async () => {
234 await
fs.rm(tempDir, { recursive:
true, force:
true });
240 if (originalCreateWebviewPanel) {
241 vscode.window.createWebviewPanel = originalCreateWebviewPanel;
252 suite(
'Constructor and Initialization', () => {
257 test(
'should create instance with default parameters', () => {
259 assert.ok(
watermark instanceof Watermark,
'Should create Watermark instance');
266 test(
'should create instance with file path parameter', async () => {
267 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
268 const watermark =
new Watermark(testFilePath);
269 assert.ok(
watermark instanceof Watermark,
'Should create Watermark instance with file path');
276 test(
'should create instance with both file path and working directory', async () => {
277 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
278 const watermark =
new Watermark(testFilePath, tempDir);
279 assert.ok(
watermark instanceof Watermark,
'Should create Watermark instance with both parameters');
286 test(
'should handle undefined parameters gracefully', () => {
287 const watermark =
new Watermark(undefined, undefined);
288 assert.ok(
watermark instanceof Watermark,
'Should handle undefined parameters');
296 suite(
'File Path Management', () => {
301 test(
'should update file path successfully', async () => {
302 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
305 const success = await
watermark.updateFilePath(testFilePath);
306 assert.strictEqual(success,
true,
'Should return true for successful file path update');
313 test(
'should update working directory successfully', async () => {
316 const success = await
watermark.updateCurrentWorkingDirectory(tempDir);
317 assert.strictEqual(success,
true,
'Should return true for successful working directory update');
324 test(
'should handle relative paths with working directory', async () => {
325 const relativePath =
'watermarks.json';
326 const fullPath =
path.join(tempDir, relativePath);
327 await
fs.writeFile(fullPath, JSON.stringify(mockWatermarks));
330 await
watermark.updateCurrentWorkingDirectory(tempDir);
331 const success = await
watermark.updateFilePath(relativePath);
333 assert.strictEqual(success,
true,
'Should handle relative paths correctly');
341 suite(
'Watermark Data Loading and Validation', () => {
346 test(
'should load and parse watermark data correctly', async () => {
347 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
348 const watermark =
new Watermark(testFilePath, tempDir);
350 const result = await
watermark.getRandomWatermark();
353 assert.ok(typeof result.fontName ===
'string',
'Watermark should have string fontName');
354 assert.ok(Array.isArray(result.watermark),
'Watermark should have array watermark content');
355 assert.ok(result.watermark.length > 0,
'Watermark array should not be empty');
356 assert.ok(result.watermark.every(line => typeof line ===
'string'),
'All watermark lines should be strings');
363 test(
'should correctly map Logo to watermark property', async () => {
364 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
365 const watermark =
new Watermark(testFilePath, tempDir);
367 const result = await
watermark.getRandomWatermark();
369 assert.ok(Array.isArray(result.watermark),
'watermark property should be an array');
370 assert.ok(result.watermark.length > 0,
'watermark content should not be empty');
371 assert.ok(result.watermark.every(line => typeof line ===
'string'),
'All watermark content lines should be strings');
378 test(
'should handle various font name formats', async () => {
379 const diverseFonts = [
380 { Logo: [
"Simple",
"Font"], fontName:
"SimpleName" },
381 { Logo: [
"Complex",
"Font"], fontName:
"Complex Font With Spaces" },
382 { Logo: [
"Special",
"Font"], fontName:
"Special-Characters_123" },
383 { Logo: [
"Unicode",
"Font"], fontName:
"Unicode Font ♦ ♠ ♣ ♥" }
385 await
fs.writeFile(testFilePath, JSON.stringify(diverseFonts));
386 const watermark =
new Watermark(testFilePath, tempDir);
388 for (let i = 0; i < 10; i++) {
389 const result = await
watermark.getRandomWatermark();
390 assert.ok(typeof result.fontName ===
'string',
'Font name should be a string');
391 assert.ok(result.fontName.length > 0,
'Font name should not be empty');
399 test(
'should handle empty logo arrays gracefully', async () => {
400 const emptyLogoWatermarks = [
401 { Logo: [], fontName:
"EmptyLogo" },
402 { Logo: [
"Non-empty"], fontName:
"NonEmpty" }
404 await
fs.writeFile(testFilePath, JSON.stringify(emptyLogoWatermarks));
405 const watermark =
new Watermark(testFilePath, tempDir);
407 const result = await
watermark.getRandomWatermark();
409 assert.ok(Array.isArray(result.watermark),
'watermark should be an array');
410 assert.ok(typeof result.fontName ===
'string',
'fontName should be a string');
418 suite(
'Random Selection Algorithm', () => {
423 test(
'should select different watermarks on multiple calls', async () => {
424 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
425 const watermark =
new Watermark(testFilePath, tempDir);
427 const selectedFonts =
new Set<string>();
430 for (let i = 0; i < 20; i++) {
431 const result = await
watermark.getRandomWatermark();
432 selectedFonts.add(result.fontName);
436 assert.ok(selectedFonts.size >= 2,
'Should select multiple different fonts');
443 test(
'should always return valid watermark from dataset', async () => {
444 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
445 const watermark =
new Watermark(testFilePath, tempDir);
447 const expectedFonts =
new Set(mockWatermarks.map(w => w.fontName));
449 for (let i = 0; i < 10; i++) {
450 const result = await
watermark.getRandomWatermark();
452 assert.ok(result.fontName,
'Should have a font name');
453 assert.ok(expectedFonts.has(result.fontName), `Font name ${result.fontName} should be from the dataset`);
454 assert.ok(Array.isArray(result.watermark),
'Watermark content should be an array');
455 assert.ok(result.watermark.length >= 0,
'Watermark should have valid content');
463 test(
'should handle single watermark file correctly', async () => {
464 const singleWatermark = [mockWatermarks[0]];
465 await
fs.writeFile(testFilePath, JSON.stringify(singleWatermark));
466 const watermark =
new Watermark(testFilePath, tempDir);
468 for (let i = 0; i < 5; i++) {
469 const result = await
watermark.getRandomWatermark();
471 assert.strictEqual(result.fontName, mockWatermarks[0].fontName);
472 assert.deepStrictEqual(result.watermark, mockWatermarks[0].Logo);
480 test(
'should properly handle watermark content arrays', async () => {
481 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
482 const watermark =
new Watermark(testFilePath, tempDir);
484 const result = await
watermark.getRandomWatermark();
486 assert.ok(Array.isArray(result.watermark),
'Watermark content should be an array');
489 result.watermark.forEach((line, index) => {
490 assert.ok(typeof line ===
'string', `Watermark line ${index} should be a
string`);
499 suite(
'Error Handling and Edge Cases', () => {
504 test(
'should throw error for empty JSON file', async () => {
505 await
fs.writeFile(testFilePath, JSON.stringify([]));
506 const watermark =
new Watermark(testFilePath, tempDir);
510 assert.fail(
'Should throw error for empty watermark array');
512 assert.ok(error instanceof Error,
'Should throw an Error instance');
520 test(
'should throw error for invalid JSON format', async () => {
521 await
fs.writeFile(testFilePath,
'{ invalid json');
522 const watermark =
new Watermark(testFilePath, tempDir);
526 assert.fail(
'Should throw error for invalid JSON');
528 assert.ok(error instanceof Error,
'Should throw an Error instance');
536 test(
'should throw error for non-array JSON content', async () => {
537 await
fs.writeFile(testFilePath, JSON.stringify({ not:
"an array" }));
538 const watermark =
new Watermark(testFilePath, tempDir);
542 assert.fail(
'Should throw error for non-array JSON content');
544 assert.ok(error instanceof Error,
'Should throw an Error instance');
552 test(
'should handle missing Logo property gracefully', async () => {
553 const malformedWatermarks = [
554 { fontName:
"MissingLogo" },
555 { Logo: [
"Valid",
"Content"], fontName:
"Valid" }
557 await
fs.writeFile(testFilePath, JSON.stringify(malformedWatermarks));
558 const watermark =
new Watermark(testFilePath, tempDir);
562 const result = await
watermark.getRandomWatermark();
564 assert.ok(typeof result.fontName ===
'string');
567 assert.ok(error instanceof Error);
575 test(
'should handle missing fontName property gracefully', async () => {
576 const malformedWatermarks = [
577 { Logo: [
"Missing",
"Font",
"Name"] },
578 { Logo: [
"Valid",
"Content"], fontName:
"Valid" }
580 await
fs.writeFile(testFilePath, JSON.stringify(malformedWatermarks));
581 const watermark =
new Watermark(testFilePath, tempDir);
585 const result = await
watermark.getRandomWatermark();
587 assert.ok(Array.isArray(result.watermark));
590 assert.ok(error instanceof Error);
598 test(
'should handle file not found error', async () => {
602 const nonExistentPath =
path.join(tempDir,
'non-existent.json');
603 await
watermark.updateFilePath(nonExistentPath);
610 assert.ok(error instanceof Error);
619 suite(
'HTML Content Generation', () => {
624 test(
'should generate valid HTML content for webview', async () => {
625 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
626 const watermark =
new Watermark(testFilePath, tempDir);
628 await
watermark.displayRandomAuthorWatermarkInWindow();
630 assert.ok(capturedHtml,
'Should generate HTML content');
631 assert.ok(capturedHtml.includes(
'<!DOCTYPE html>'),
'Should be valid HTML');
632 assert.ok(capturedHtml.includes(
'<html lang="en">'),
'Should have language attribute');
633 assert.ok(capturedHtml.includes(
'<body>'),
'Should have body tag');
640 test(
'should include watermark content in HTML', async () => {
641 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
642 const watermark =
new Watermark(testFilePath, tempDir);
644 await
watermark.displayRandomAuthorWatermarkInWindow();
646 assert.ok(capturedHtml.includes(
'<pre id="ascii">'),
'Should include ASCII art container');
648 const preMatch = capturedHtml.match(/<pre
id=
"ascii">(.*?)<\/pre>/s);
649 assert.ok(preMatch,
'Should have ASCII art content');
650 assert.ok(preMatch[1].length > 0,
'ASCII art content should not be empty');
657 test(
'should include interactive buttons in HTML', async () => {
658 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
659 const watermark =
new Watermark(testFilePath, tempDir);
661 await
watermark.displayRandomAuthorWatermarkInWindow();
663 assert.ok(capturedHtml.includes(
'id="copyBtn"'),
'Should include copy button');
664 assert.ok(capturedHtml.includes(
'id="zoomInBtn"'),
'Should include zoom in button');
665 assert.ok(capturedHtml.includes(
'id="zoomOutBtn"'),
'Should include zoom out button');
672 test(
'should include CSS styling', async () => {
673 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
674 const watermark =
new Watermark(testFilePath, tempDir);
676 await
watermark.displayRandomAuthorWatermarkInWindow();
678 assert.ok(capturedHtml.includes(
'<style>'),
'Should include CSS styling');
679 assert.ok(capturedHtml.includes(
'font-family:'),
'Should have font family styling');
680 assert.ok(capturedHtml.includes(
'pre {'),
'Should have pre tag styling for ASCII art');
687 test(
'should include font name in display', async () => {
688 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
689 const watermark =
new Watermark(testFilePath, tempDir);
691 await
watermark.displayRandomAuthorWatermarkInWindow();
694 const includesFontName = mockWatermarks.some(w =>
695 capturedHtml.includes(w.fontName) || lastCreatedPanel.title.includes(w.fontName)
697 assert.ok(includesFontName,
'Should display font name');
704 test(
'should include author information', async () => {
705 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
706 const watermark =
new Watermark(testFilePath, tempDir);
708 await
watermark.displayRandomAuthorWatermarkInWindow();
710 assert.ok(capturedHtml.includes(
'Henry Letellier'),
'Should include author name');
717 test(
'should handle empty watermark content gracefully', async () => {
718 const emptyWatermarks = [{ Logo: [], fontName:
"Empty" }];
719 await
fs.writeFile(testFilePath, JSON.stringify(emptyWatermarks));
720 const watermark =
new Watermark(testFilePath, tempDir);
723 await
watermark.displayRandomAuthorWatermarkInWindow();
725 assert.ok(capturedHtml,
'Should generate HTML even with empty content');
726 assert.ok(capturedHtml.includes(
'<!DOCTYPE html>'),
'Should be valid HTML');
734 suite(
'JavaScript Functionality', () => {
739 test(
'should include copy button script', async () => {
740 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
741 const watermark =
new Watermark(testFilePath, tempDir);
743 await
watermark.displayRandomAuthorWatermarkInWindow();
745 assert.ok(capturedHtml.includes(
"getElementById('copyBtn')"),
'Should include copy button script');
746 assert.ok(capturedHtml.includes(
'navigator.clipboard.writeText'),
'Should use clipboard API');
747 assert.ok(capturedHtml.includes(
"vscode.postMessage({ type: 'copied' })"),
'Should post message to VS Code');
754 test(
'should include zoom functionality script', async () => {
755 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
756 const watermark =
new Watermark(testFilePath, tempDir);
758 await
watermark.displayRandomAuthorWatermarkInWindow();
760 assert.ok(capturedHtml.includes(
'updateFontSize'),
'Should include font size update function');
761 assert.ok(capturedHtml.includes(
"getElementById('zoomInBtn')"),
'Should include zoom in handler');
762 assert.ok(capturedHtml.includes(
"getElementById('zoomOutBtn')"),
'Should include zoom out handler');
763 assert.ok(capturedHtml.includes(
'currentSize'),
'Should track current font size');
770 test(
'should include VS Code API integration', async () => {
771 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
772 const watermark =
new Watermark(testFilePath, tempDir);
774 await
watermark.displayRandomAuthorWatermarkInWindow();
776 assert.ok(capturedHtml.includes(
'acquireVsCodeApi()'),
'Should acquire VS Code API');
777 assert.ok(capturedHtml.includes(
'vscode.postMessage'),
'Should use VS Code message posting');
784 test(
'should implement font size constraints in zoom', async () => {
785 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
786 const watermark =
new Watermark(testFilePath, tempDir);
788 await
watermark.displayRandomAuthorWatermarkInWindow();
791 assert.ok(capturedHtml.includes(
'>= 2'),
'Should have minimum font size constraint');
793 assert.ok(capturedHtml.includes(
'currentSize = 20'),
'Should initialize font size');
800 test(
'should include debug logging for zoom functionality', async () => {
801 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
802 const watermark =
new Watermark(testFilePath, tempDir);
804 await
watermark.displayRandomAuthorWatermarkInWindow();
806 assert.ok(capturedHtml.includes(
'console.log'),
'Should include console logging');
807 assert.ok(capturedHtml.includes(
'sizeDifference'),
'Should log size difference');
808 assert.ok(capturedHtml.includes(
'currentSize'),
'Should log current size');
816 suite(
'Integration and Message Handling', () => {
821 test(
'should setup message handler for copy events', async () => {
822 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
823 const watermark =
new Watermark(testFilePath, tempDir);
825 await
watermark.displayRandomAuthorWatermarkInWindow();
828 assert.ok(lastCreatedPanel,
'Should create webview panel');
829 assert.ok(lastCreatedWebview,
'Should create webview');
832 if (lastCreatedWebview && lastCreatedWebview.postMessage) {
833 lastCreatedWebview.postMessage({
type:
'copied' });
837 assert.ok(
true,
'Message handling should not throw errors');
844 test(
'should create webview with correct parameters', async () => {
845 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
846 const watermark =
new Watermark(testFilePath, tempDir);
848 await
watermark.displayRandomAuthorWatermarkInWindow();
850 assert.ok(lastCreatedPanel,
'Should create webview panel');
851 assert.strictEqual(lastCreatedPanel.showOptions,
vscode.ViewColumn.One,
'Should use ViewColumn.One');
852 assert.ok(lastCreatedPanel.options.enableScripts,
'Should enable scripts');
855 const expectedFontNames = mockWatermarks.map(w => w.fontName);
856 assert.ok(expectedFontNames.includes(lastCreatedPanel.title),
'Title should be a font name');
863 test(
'should handle message communication properly', async () => {
864 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
865 const watermark =
new Watermark(testFilePath, tempDir);
867 await
watermark.displayRandomAuthorWatermarkInWindow();
870 const testMessages = [
873 {
type:
'test', data:
'value' }
876 testMessages.forEach(message => {
877 if (lastCreatedWebview && lastCreatedWebview.postMessage) {
879 lastCreatedWebview.postMessage(message);
881 assert.fail(`Should handle message ${JSON.stringify(message)} without error`);
886 assert.ok(
true,
'All message types handled without errors');
894 suite(
'Performance and Memory Management', () => {
899 test(
'should handle multiple rapid watermark selections', async () => {
900 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
901 const watermark =
new Watermark(testFilePath, tempDir);
903 const startTime = Date.now();
906 for (let i = 0; i < 50; i++) {
910 const endTime = Date.now();
911 const duration = endTime - startTime;
914 assert.ok(duration < 5000,
'Multiple selections should be reasonably fast');
921 test(
'should reuse file loader instances efficiently', async () => {
922 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
923 const watermark =
new Watermark(testFilePath, tempDir);
926 const watermark1 = await
watermark.getRandomWatermark();
927 const watermark2 = await
watermark.getRandomWatermark();
929 assert.ok(typeof watermark1.fontName ===
'string');
930 assert.ok(typeof watermark2.fontName ===
'string');
933 assert.ok(Array.isArray(watermark1.watermark));
934 assert.ok(Array.isArray(watermark2.watermark));
941 test(
'should handle large watermark collections', async () => {
944 for (let i = 0; i < 100; i++) {
945 largeCollection.push({
946 Logo: [`Watermark ${i}`, `Line 2 of ${i}`, `Line 3 of ${i}`],
951 await
fs.writeFile(testFilePath, JSON.stringify(largeCollection));
952 const watermark =
new Watermark(testFilePath, tempDir);
955 const result = await
watermark.getRandomWatermark();
956 assert.ok(result.fontName.startsWith(
'Font'));
957 assert.ok(Array.isArray(result.watermark));
958 assert.strictEqual(result.watermark.length, 3);
965 test(
'should handle file path updates without memory leaks', async () => {
969 const file1 =
path.join(tempDir,
'watermarks1.json');
970 const file2 =
path.join(tempDir,
'watermarks2.json');
972 await
fs.writeFile(file1, JSON.stringify([mockWatermarks[0]]));
973 await
fs.writeFile(file2, JSON.stringify([mockWatermarks[1]]));
977 const result1 = await
watermark.getRandomWatermark();
980 const result2 = await
watermark.getRandomWatermark();
983 const result3 = await
watermark.getRandomWatermark();
986 assert.strictEqual(result1.fontName, mockWatermarks[0].fontName);
987 assert.strictEqual(result2.fontName, mockWatermarks[1].fontName);
988 assert.strictEqual(result3.fontName, mockWatermarks[0].fontName);
996 suite(
'Edge Cases and Robustness', () => {
1001 test(
'should handle Unicode characters in watermarks', async () => {
1002 const unicodeWatermarks = [
1005 "╔══════════════════════════════════════╗",
1007 "║ ♦ ♠ ♣ ♥ ★ ☆ ☀ ☁ ☂ ☃ ☄ ☎ ☏ ☐ ☑ ║",
1008 "║ ♪ ♫ ♬ ♭ ♮ ♯ ♰ ♱ ♲ ♳ ♴ ♵ ♶ ♷ ♸ ║",
1009 "╚══════════════════════════════════════╝"
1011 fontName:
"Unicode Test"
1015 await
fs.writeFile(testFilePath, JSON.stringify(unicodeWatermarks));
1016 const watermark =
new Watermark(testFilePath, tempDir);
1018 const result = await
watermark.getRandomWatermark();
1020 assert.strictEqual(result.fontName,
"Unicode Test");
1021 assert.ok(result.watermark.some(line => line.includes(
'♦')),
'Should preserve Unicode characters');
1028 test(
'should handle very long watermark lines', async () => {
1029 const longLineWatermark = [
1036 fontName:
"Long Lines"
1040 await
fs.writeFile(testFilePath, JSON.stringify(longLineWatermark));
1041 const watermark =
new Watermark(testFilePath, tempDir);
1043 const result = await
watermark.getRandomWatermark();
1045 assert.strictEqual(result.fontName,
"Long Lines");
1046 assert.strictEqual(result.watermark[0].length, 1000);
1047 assert.strictEqual(result.watermark[2].length, 500);
1054 test(
'should handle watermarks with many lines', async () => {
1055 const manyLinesWatermark = [
1057 Logo: Array.from({ length: 100 }, (_, i) => `Line ${i + 1}`),
1058 fontName:
"Many Lines"
1062 await
fs.writeFile(testFilePath, JSON.stringify(manyLinesWatermark));
1063 const watermark =
new Watermark(testFilePath, tempDir);
1065 const result = await
watermark.getRandomWatermark();
1067 assert.strictEqual(result.fontName,
"Many Lines");
1068 assert.strictEqual(result.watermark.length, 100);
1069 assert.strictEqual(result.watermark[0],
"Line 1");
1070 assert.strictEqual(result.watermark[99],
"Line 100");
1077 test(
'should handle special characters in font names', async () => {
1078 const specialNameWatermarks = [
1079 { Logo: [
"Test"], fontName:
"Font/With\\Special:Characters" },
1080 { Logo: [
"Test"], fontName:
"Font<>With|Symbols" },
1081 { Logo: [
"Test"], fontName:
"Font\"With'Quotes" }
1084 await
fs.writeFile(testFilePath, JSON.stringify(specialNameWatermarks));
1085 const watermark =
new Watermark(testFilePath, tempDir);
1087 for (let i = 0; i < 10; i++) {
1088 const result = await
watermark.getRandomWatermark();
1089 assert.ok(typeof result.fontName ===
'string');
1090 assert.ok(result.fontName.length > 0);
1098 test(
'should handle JSON with extra properties', async () => {
1099 const extendedWatermarks = [
1101 Logo: [
"Test",
"Watermark"],
1102 fontName:
"Test Font",
1103 extraProperty:
"Should be ignored",
1109 await
fs.writeFile(testFilePath, JSON.stringify(extendedWatermarks));
1110 const watermark =
new Watermark(testFilePath, tempDir);
1112 const result = await
watermark.getRandomWatermark();
1115 assert.strictEqual(result.fontName,
"Test Font");
1116 assert.deepStrictEqual(result.watermark, [
"Test",
"Watermark"]);
1124 suite(
'Type Safety and Data Integrity', () => {
1129 test(
'should maintain correct types throughout selection process', async () => {
1130 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
1131 const watermark =
new Watermark(testFilePath, tempDir);
1133 for (let i = 0; i < 10; i++) {
1134 const result = await
watermark.getRandomWatermark();
1137 assert.strictEqual(typeof result,
'object',
'Result should be an object');
1138 assert.strictEqual(typeof result.fontName,
'string',
'fontName should be string');
1139 assert.ok(Array.isArray(result.watermark),
'watermark should be array');
1142 result.watermark.forEach((line, index) => {
1143 assert.strictEqual(typeof line,
'string', `Line ${index} should be
string`);
1152 test(
'should validate watermark interface compliance', async () => {
1153 await
fs.writeFile(testFilePath, JSON.stringify(mockWatermarks));
1154 const watermark =
new Watermark(testFilePath, tempDir);
1156 const result = await
watermark.getRandomWatermark();
1159 const watermarkInterface:
watermark = result;
1160 assert.ok(watermarkInterface.fontName,
'Should have fontName property');
1161 assert.ok(watermarkInterface.watermark,
'Should have watermark property');
1164 const keys = Object.keys(result);
1165 assert.ok(keys.includes(
'fontName'),
'Should include fontName');
1166 assert.ok(keys.includes(
'watermark'),
'Should include watermark');
Mock implementation of VS Code webview panel for testing.
constructor(public viewType:string, public title:string, public showOptions:vscode.ViewColumn, public options:vscode.WebviewPanelOptions &vscode.WebviewOptions)
Constructs a new mock webview panel with specified configuration.
Mock implementation of VS Code webview for testing.
postMessage(message:any)
Posts a message to all registered handlers.
onDidReceiveMessage(handler:(message:any)=> void)
Registers a message handler for webview communication.
get html()
Gets the current HTML content of the webview.
Interface for test watermark data matching the JSON structure.
Structure representing a loaded ASCII art watermark with font metadata.
export const Record< string,(...args:any[])=> string
import *as vscode from vscode
import *as path from path
import *as assert from assert