-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest.js
More file actions
377 lines (353 loc) · 12.3 KB
/
test.js
File metadata and controls
377 lines (353 loc) · 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
"use strict";
// Disable first-run modal in the test build
localStorage.setItem("firstRunAcknowledged", "true");
// Global error handler for unexpected errors
window.addEventListener("error", function (event) {
console.error("Global error caught:", event.error);
window.testResults = {
success: false,
errors: [{
description: "Global error",
errors: [event.error ? event.error.toString() : event.message]
}]
};
window.testStatus = "failed";
});
// =============================================
// Base class for all test cases
// =============================================
class TestCase {
constructor({ description, input, expectedOutput }) {
this.description = description;
this.input = input;
this.expectedOutput = expectedOutput;
}
async run() {
throw new Error("run() must be implemented in subclass");
}
}
// =============================================
// Simple I/O Test Case
// =============================================
class SimpleIOTestCase extends TestCase {
async run() {
const anonymizer = new window.Anonymizer();
anonymizer.setText(this.input);
await anonymizer.anonymize();
const anonymizedOutput = anonymizer.getText();
const deanonymizedOutput = anonymizer.deanonymize();
let errors = [];
if (anonymizedOutput !== this.expectedOutput) {
errors.push(`Anonymize: expected "${this.expectedOutput}", but got "${anonymizedOutput}"`);
}
if (deanonymizedOutput !== this.input) {
errors.push(`Deanonymize: expected "${this.input}", but got "${deanonymizedOutput}"`);
}
return { description: this.description, passed: errors.length === 0, errors };
}
}
// =============================================
// Custom Placeholder Test Case
// =============================================
class CustomPlaceholderTestCase extends TestCase {
constructor(opts) {
super(opts);
this.customPlaceholder = opts.customPlaceholder;
}
async run() {
const anonymizer = new window.Anonymizer();
anonymizer.setText(this.input);
if (this.customPlaceholder) {
anonymizer.addCustomPlaceholder(
this.customPlaceholder.label,
this.customPlaceholder.pattern
);
}
await anonymizer.anonymize();
const anonymizedOutput = anonymizer.getText();
const deanonymizedOutput = anonymizer.deanonymize();
let errors = [];
if (anonymizedOutput !== this.expectedOutput) {
errors.push(`Anonymize: expected "${this.expectedOutput}", but got "${anonymizedOutput}"`);
}
if (deanonymizedOutput !== this.input) {
errors.push(`Deanonymize: expected "${this.input}", but got "${deanonymizedOutput}"`);
}
return { description: this.description, passed: errors.length === 0, errors };
}
}
// =============================================
// List of all test cases
// =============================================
const testCases = [
new SimpleIOTestCase({
description: "Too short number (2 digits) should not be detected",
input: "12",
expectedOutput: "12"
}),
new SimpleIOTestCase({
description: "Minimum valid number (3 digits)",
input: "123",
expectedOutput: "[Number]"
}),
new SimpleIOTestCase({
description: "Number with hyphen",
input: "12341324-132424",
expectedOutput: "[Number]"
}),
new SimpleIOTestCase({
description: "Number with dots",
input: "1234.32411.1234",
expectedOutput: "[Number]"
}),
new SimpleIOTestCase({
description: "Number with slashes",
input: "1324/21342/213123",
expectedOutput: "[Number]"
}),
new SimpleIOTestCase({
description: "Composite numbers test",
input: "Order 12, then 123, then 12341324-132424, 1234.32411.1234 and 1324/21342/213123.",
expectedOutput: "Order 12, then [Number_4], then [Number_2], [Number_3] and [Number]."
}),
new SimpleIOTestCase({
description: "Name with greeting prefix detection",
input: "Hallo John",
expectedOutput: "Hallo [Name]"
}),
new SimpleIOTestCase({
description: "Composite name test with full name",
input: "Guten Tag Maria Müller, wie geht es?",
expectedOutput: "Guten Tag [Name], wie geht es?"
}),
new SimpleIOTestCase({
description: "Name without greeting prefix should not be detected",
input: "John",
expectedOutput: "John"
}),
new SimpleIOTestCase({
description: "Composite test with number and name",
input: "Order 123 and Hallo John and Guten Tag Maria Müller",
expectedOutput: "Order [Number] and Hallo [Name_2] and Guten Tag [Name]"
}),
new SimpleIOTestCase({
description: "Simple email detection",
input: "user@example.com",
expectedOutput: "[Email]"
}),
new SimpleIOTestCase({
description: "Composite email test",
input: "Contact: user@example.com for info.",
expectedOutput: "Contact: [Email] for info."
}),
new SimpleIOTestCase({
description: "Multiple email detection",
input: "Emails: user@example.com, admin@example.org.",
expectedOutput: "Emails: [Email_2], [Email]."
}),
new SimpleIOTestCase({
description: "False positive email should not be detected",
input: "Not an email: user_at_example.com",
expectedOutput: "Not an email: user_at_example.com"
}),
new CustomPlaceholderTestCase({
description: "Custom literal test",
input: "Das ist ein CUSTOM text.",
expectedOutput: "Das ist ein [Custom] text.",
customPlaceholder: { label: "Custom", pattern: "CUSTOM" }
}),
new CustomPlaceholderTestCase({
description: "Custom regex literal test",
input: "FOO1 and FOO2.",
expectedOutput: "[Custom] and [Custom_2].",
customPlaceholder: { label: "Custom", pattern: "/FOO\\d/g" }
}),
// --- Case‑insensitive NamePrefix Tests ---
new SimpleIOTestCase({
description: "Lowercase greeting prefix 'hallo John'",
input: "hallo John",
expectedOutput: "hallo [Name]"
}),
new SimpleIOTestCase({
description: "Uppercase greeting prefix 'HALLO John'",
input: "HALLO John",
expectedOutput: "HALLO [Name]"
}),
new SimpleIOTestCase({
description: "Mixed‑case prefix 'gUtEn TaG Maria Müller'",
input: "gUtEn TaG Maria Müller, wie geht es?",
expectedOutput: "gUtEn TaG [Name], wie geht es?"
}),
new SimpleIOTestCase({
description: "Informal 'hey Alice' prefix lowercase",
input: "hey Alice, schön dich zu sehen.",
expectedOutput: "hey [Name], schön dich zu sehen."
}),
new SimpleIOTestCase({
description: "Formal 'Sehr geehrte Frau Müller' prefix mixed case",
input: "sEhR gEeHrTe fRaU Müller",
expectedOutput: "sEhR gEeHrTe fRaU [Name]"
}),
];
// Zusätzliche Testfälle für kontextbezogene Namens-Erkennung
const additionalNameTestCases = [
new SimpleIOTestCase({
description: "Formal salutation with Prof. and Dr.",
input: "Herr Prof. Dr. Schmidt",
expectedOutput: "Herr Prof. Dr. [Name]"
}),
new SimpleIOTestCase({
description: "Formal salutation with trailing period",
input: "Herr Prof. Dr. Schmidt.",
expectedOutput: "Herr Prof. Dr. [Name]."
}),
new SimpleIOTestCase({
description: "Titles in reversed order",
input: "Herr Dr. Prof. Schmidt",
expectedOutput: "Herr Dr. Prof. [Name]"
}),
new SimpleIOTestCase({
description: "Informal greeting with multiple titles",
input: "Hallo liebe Frau Prof. Dr. Uta Müller",
expectedOutput: "Hallo liebe Frau Prof. Dr. [Name]"
}),
new SimpleIOTestCase({
description: "lowercase informal greeting with titles",
input: "hallo liebe frau prof. dr. uta müller",
expectedOutput: "hallo liebe frau prof. dr. uta müller" // No detection
}),
new SimpleIOTestCase({
description: "Complex formal salutation with engineering title",
input: "Sehr geehrter Herr Prof. Dr. Ing. Karl-Heinz Müller",
expectedOutput: "Sehr geehrter Herr Prof. Dr. Ing. [Name]"
}),
new SimpleIOTestCase({
description: "Complex formal salutation with medical title",
input: "Sehr geehrte Frau Dr. med. Anna-Lena Schmidt",
expectedOutput: "Sehr geehrte Frau Dr. med. [Name]"
}),
new SimpleIOTestCase({
description: "Greeting with French accented name",
input: "Guten Tag Frau François Dupont",
expectedOutput: "Guten Tag Frau [Name]"
}),
new SimpleIOTestCase({
description: "Welcome phrase with Spanish accented compound name",
input: "Guten Tag Frau José-Luis García, willkommen.",
expectedOutput: "Guten Tag Frau [Name], willkommen."
}),
new SimpleIOTestCase({
description: "Mixed-case formal salutation",
input: "sEhR gEeHrTe fRaU Dr. Élodie Müller",
expectedOutput: "sEhR gEeHrTe fRaU Dr. [Name]"
}),
new SimpleIOTestCase({
description: "Evening greeting with titles",
input: "Guten Abend Herr Müller-Schmidt",
expectedOutput: "Guten Abend Herr [Name]"
}),
new SimpleIOTestCase({
description: "Multiple-word hyphenated name",
input: "Guten Tag Frau Anna-Lena von der Leyen",
expectedOutput: "Guten Tag Frau [Name]"
}),
new SimpleIOTestCase({
description: "Uppercase informal with titles and umlaut",
input: "HALLO FRAU PROF. DR. BÄCKER",
expectedOutput: "HALLO FRAU PROF. DR. [Name]"
}),
];
additionalNameTestCases.forEach(tc => testCases.push(tc));
// =============================================
// Test runner
// =============================================
async function runAllTests() {
let allPassed = true;
const errorList = [];
for (const tc of testCases) {
try {
const result = await tc.run();
if (!result.passed) {
allPassed = false;
errorList.push({ description: result.description, errors: result.errors });
}
} catch (err) {
allPassed = false;
errorList.push({ description: tc.description, errors: [err.message] });
}
}
return { success: allPassed, errors: errorList };
}
// =============================================
// Start tests and display modal
// =============================================
(async () => {
window.testStatus = "started";
try {
window.testResults = await runAllTests();
window.testStatus = "completed";
console.log("Tests completed.", window.testResults);
} catch (err) {
console.error("Tests aborted:", err);
window.testResults = {
success: false,
errors: [{
description: "Test script aborted",
errors: [err.message || err.toString()]
}]
};
window.testStatus = "failed";
}
function showTestResults() {
// Open the modal
window.Modal.showModal("testResultsModal");
// Container for results
const container = document.getElementById("testResultsContent");
container.innerHTML = "";
// Summary
const total = testCases.length;
const failed = window.testResults.errors.length;
const summary = document.createElement("p");
summary.textContent = failed > 0
? `${failed} of ${total} tests failed.`
: `All ${total} tests passed successfully!`;
container.appendChild(summary);
// Detailed error table if there are failures
if (failed > 0) {
const table = document.createElement("table");
table.style.width = "100%";
table.style.borderCollapse = "collapse";
const thead = document.createElement("thead");
thead.innerHTML = `
<tr>
<th style="text-align:left;padding:4px">Test</th>
<th style="text-align:left;padding:4px">Errors</th>
</tr>`;
table.appendChild(thead);
const tbody = document.createElement("tbody");
for (const err of window.testResults.errors) {
const tr = document.createElement("tr");
const messages = err.errors.map(e => `<li>${e}</li>`).join("");
tr.innerHTML = `
<td style="padding:4px;vertical-align:top">${err.description}</td>
<td style="padding:4px"><ul style="margin:0 0 0 1em;padding:0;">${messages}</ul></td>`;
tbody.appendChild(tr);
}
table.appendChild(tbody);
container.appendChild(table);
}
// Copy button handler
const copyBtn = document.getElementById("copyTestErrorsBtn");
copyBtn.onclick = () => {
const text = JSON.stringify(window.testResults, null, 2);
navigator.clipboard.writeText(text);
copyBtn.textContent = "Copied!";
setTimeout(() => copyBtn.textContent = "Copy error messages", 2000);
};
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", showTestResults);
} else {
showTestResults();
}
})();