Initial commit

This commit is contained in:
Mandy
2026-07-25 21:13:35 +02:00
commit e8f88cceac
9 changed files with 4070 additions and 0 deletions
+229
View File
@@ -0,0 +1,229 @@
import { test, describe, before } from 'node:test';
import assert from 'node:assert/strict';
import fs from 'fs';
import { JSDOM } from 'jsdom';
import crypto from 'node:crypto';
describe('Secret Message Studio - Comprehensive Test Suite', () => {
let dom;
let window;
let document;
before(async () => {
const htmlContent = fs.readFileSync('index.html', 'utf8');
dom = new JSDOM(htmlContent, {
url: 'http://localhost/index.html',
runScripts: 'dangerously',
beforeParse(win) {
// Polyfill Web Crypto API
Object.defineProperty(win, 'crypto', {
value: crypto.webcrypto,
writable: true,
});
// Mock QRCode canvas drawer to prevent external network fetches
win.QRCode = {
toCanvas: (canvas, text, opts) => {
const ctx = canvas.getContext('2d');
if (ctx) {
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
},
};
// Polyfill animationFrame
win.requestAnimationFrame = (cb) => setTimeout(cb, 16);
win.cancelAnimationFrame = (id) => clearTimeout(id);
},
});
window = dom.window;
document = window.document;
// Allow inline script execution to settle
await new Promise((r) => setTimeout(r, 100));
});
test('DOM elements initialized properly', () => {
assert.ok(document.querySelector('#messageInput'), 'messageInput exists');
assert.ok(document.querySelector('#createBtn'), 'createBtn exists');
assert.ok(document.querySelector('#openBtn'), 'openBtn exists');
assert.ok(document.querySelector('#decodedResult'), 'decodedResult exists');
});
test('Language toggle works (DE -> EN -> DE)', () => {
const deBtn = document.querySelector('[data-lang="de"]');
const enBtn = document.querySelector('[data-lang="en"]');
enBtn.click();
assert.strictEqual(window.state.lang, 'en');
assert.strictEqual(document.querySelector('#createBtn').textContent, 'Create');
deBtn.click();
assert.strictEqual(window.state.lang, 'de');
assert.strictEqual(document.querySelector('#createBtn').textContent, 'Erstellen');
});
test('Tab navigation works (Encode <-> Decode)', () => {
const decodeTab = document.querySelector('[data-tab="decode"]');
const encodeTab = document.querySelector('[data-tab="encode"]');
decodeTab.click();
assert.strictEqual(window.state.tab, 'decode');
assert.ok(document.querySelector('#decodeView').classList.contains('active'));
encodeTab.click();
assert.strictEqual(window.state.tab, 'encode');
assert.ok(document.querySelector('#encodeView').classList.contains('active'));
});
test('Password Generator button works', () => {
const genBtn = document.querySelector('#generatePasswordBtn');
const passInput = document.querySelector('#passwordInput');
const secureToggle = document.querySelector('#secureToggle');
genBtn.click();
assert.ok(passInput.value.length >= 12, 'Password generated with sufficient length');
assert.strictEqual(secureToggle.checked, true, 'Secure toggle activated');
});
test('Base64 Encoding & Decoding flow', async () => {
document.querySelector('#clearEncodeBtn').click();
document.querySelector('#messageInput').value = 'Test Secret Message 123';
document.querySelector('#toInput').value = 'Alice';
document.querySelector('#fromInput').value = 'Bob';
document.querySelector('#createBtn').click();
// Give microtask queue time to finish async createPayload
await new Promise((r) => setTimeout(r, 150));
assert.ok(window.state.payload.startsWith('sm2.'), 'Payload generated with sm2 prefix');
const displayCode = window.state.displayCode;
assert.ok(displayCode, 'Display code is present');
// Switch to decode and open message with fade mode
document.querySelector('[data-tab="decode"]').click();
document.querySelector('#revealMode').value = 'fade';
document.querySelector('#decodeInput').value = displayCode;
document.querySelector('#openBtn').click();
await new Promise((r) => setTimeout(r, 200));
const resultText = document.querySelector('#decodedResult').textContent;
assert.strictEqual(resultText, 'Test Secret Message 123', 'Message correctly decoded');
});
test('AES Password Encryption & Decryption flow', async () => {
document.querySelector('[data-tab="encode"]').click();
document.querySelector('#clearEncodeBtn').click();
document.querySelector('#messageInput').value = 'Top Secret Encrypted';
document.querySelector('#passwordInput').value = 'MySuperSecretPass123!';
document.querySelector('#secureToggle').checked = true;
document.querySelector('#createBtn').click();
await new Promise((r) => setTimeout(r, 150));
const payload = window.state.payload;
assert.ok(payload.startsWith('sm2.'), 'Encrypted payload created');
// Decode with wrong password -> should fail
document.querySelector('[data-tab="decode"]').click();
document.querySelector('#revealMode').value = 'fade';
document.querySelector('#decodeInput').value = payload;
document.querySelector('#decodePassword').value = 'WrongPassword';
document.querySelector('#openBtn').click();
await new Promise((r) => setTimeout(r, 200));
assert.strictEqual(document.querySelector('#toast').textContent, 'Dieses Geheimnis braucht das richtige Passwort.');
// Decode with correct password -> should succeed
document.querySelector('#decodePassword').value = 'MySuperSecretPass123!';
document.querySelector('#openBtn').click();
await new Promise((r) => setTimeout(r, 300));
assert.strictEqual(document.querySelector('#decodedResult').textContent, 'Top Secret Encrypted');
});
test('Decoy Message flow on wrong password', async () => {
document.querySelector('[data-tab="encode"]').click();
document.querySelector('#clearEncodeBtn').click();
document.querySelector('#messageInput').value = 'Real Secret';
document.querySelector('#passwordInput').value = 'RealPassword123';
document.querySelector('#secureToggle').checked = true;
document.querySelector('#decoyInput').value = 'Fake Decoy Message';
document.querySelector('#createBtn').click();
await new Promise((r) => setTimeout(r, 150));
const payload = window.state.payload;
// Decode with wrong password -> should display Decoy message
document.querySelector('[data-tab="decode"]').click();
document.querySelector('#revealMode').value = 'fade';
document.querySelector('#decodeInput').value = payload;
document.querySelector('#decodePassword').value = 'WrongPassword';
document.querySelector('#openBtn').click();
await new Promise((r) => setTimeout(r, 300));
assert.strictEqual(document.querySelector('#decodedResult').textContent, 'Fake Decoy Message');
});
test('Emoji Code conversion', () => {
const originalText = 'sm2.SGVsbG8';
const emojiCode = window.toEmojiCode(originalText);
const convertedBack = window.fromEmojiCode(emojiCode);
assert.strictEqual(convertedBack, originalText, 'Emoji code roundtrip succeeds');
});
test('Steganography Embedding & Extraction', () => {
const canvas = window.document.createElement('canvas');
canvas.width = 400;
canvas.height = 400;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#ff0000';
ctx.fillRect(0, 0, 400, 400);
const testPayload = 'sm2.StegoPayloadTesting123';
const success = window.embedPayloadInCanvas(canvas, testPayload);
assert.strictEqual(success, true, 'Payload successfully embedded in canvas');
const extracted = window.extractPayloadFromCanvas(canvas);
assert.strictEqual(extracted, testPayload, 'Extracted payload matches original');
});
test('Design Undo & Redo functionality', () => {
const initialQrX = window.state.design.qrX;
// Change slider
const qrXRange = document.querySelector('#qrXRange');
qrXRange.value = '75';
qrXRange.dispatchEvent(new window.Event('input'));
assert.strictEqual(window.state.design.qrX, 75);
// Click Undo
document.querySelector('#undoDesignBtn').click();
assert.strictEqual(window.state.design.qrX, initialQrX, 'Undo restored initial QR X');
// Click Redo
document.querySelector('#redoDesignBtn').click();
assert.strictEqual(window.state.design.qrX, 75, 'Redo restored updated QR X');
});
test('Clear Encode & Clear Decode buttons', () => {
document.querySelector('#messageInput').value = 'Some message';
document.querySelector('#clearEncodeBtn').click();
assert.strictEqual(document.querySelector('#messageInput').value, '', 'Message input cleared');
document.querySelector('#decodeInput').value = 'Some code';
document.querySelector('#clearDecodeBtn').click();
assert.strictEqual(document.querySelector('#decodeInput').value, '', 'Decode input cleared');
});
});