Class_generator/tests/fixtures/edge-case-data.js
StillHammer cb614a439d Add comprehensive test suite with unit tests and integration tests
- Complete test infrastructure with runners, helpers, and fixtures
- Unit tests for core modules: EnvConfig, ContentScanner, GameLoader
- Integration tests for proxy, content loading, and navigation
- Edge case tests covering data corruption, network failures, security
- Stress tests with 100+ concurrent requests and performance monitoring
- Test fixtures with malicious content samples and edge case data
- Comprehensive README with usage instructions and troubleshooting

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-16 11:37:08 +08:00

378 lines
12 KiB
JavaScript

// Fixtures spécifiques pour les edge cases
export const corruptedJSONSamples = [
'{"name": "Incomplete JSON"', // JSON tronqué
'{"name": "Bad JSON",}', // Virgule finale
'{name: "No quotes"}', // Clés sans guillemets
'{"name": "Unicode\\uXXXX"}', // Unicode invalide
'{"circular": {"self":', // JSON circulaire interrompu
'{}{}', // Plusieurs objets JSON
'null', // JSON valide mais pas un objet
'[]', // Array au lieu d'objet
'"just a string"', // String au lieu d'objet
'{"huge": "' + 'x'.repeat(100000) + '"}' // Énorme chaîne
];
export const maliciousContentSamples = [
{
name: "XSS Attempt",
vocabulary: {
"<script>alert('xss')</script>": "malicious",
"javascript:alert(1)": "dangerous"
}
},
{
name: "SQL Injection Like",
vocabulary: {
"'; DROP TABLE vocabulary; --": "injection",
"1' OR '1'='1": "boolean"
}
},
{
name: "Path Traversal",
vocabulary: {
"../../../etc/passwd": "traversal",
"..\\\\..\\\\..\\\\windows\\\\system32": "windows"
}
},
{
name: "Null Bytes",
vocabulary: {
"test\\x00hidden": "null byte",
"normal\\0text": "embedded null"
}
}
];
export const extremeDataSamples = {
// Objet avec une profondeur excessive
deeplyNested: (() => {
let obj = { vocabulary: {} };
let current = obj;
for (let i = 0; i < 1000; i++) {
current.nested = { level: i };
current = current.nested;
}
return obj;
})(),
// Objet avec énormément de propriétés
manyProperties: (() => {
const obj = { name: "Many Props", vocabulary: {} };
for (let i = 0; i < 10000; i++) {
obj.vocabulary[`word${i}`] = `translation${i}`;
}
return obj;
})(),
// Chaînes très longues
longStrings: {
name: "A".repeat(100000),
description: "B".repeat(50000),
vocabulary: {
"test": "C".repeat(200000)
}
},
// Caractères spéciaux et Unicode
unicodeHeavy: {
name: "Unicode Test 🚀🎉💥🌟⭐🔥💯🎯🌈",
vocabulary: {
"你好": "Hello in Chinese",
"🏠🏡🏢": "Buildings",
"café": "Coffee with accent",
"naïve": "French word",
"Москва": "Moscow in Russian",
"العربية": "Arabic text",
"🧪⚗️🔬": "Science emojis",
"\\u{1F600}": "Unicode escape",
"\\x41\\x42\\x43": "Hex escapes"
}
},
// Données avec types mixtes (pas recommandé mais possible)
mixedTypes: {
name: "Mixed Types",
vocabulary: {
"string": "normal",
"number": 123,
"boolean": true,
"null": null,
"array": ["item1", "item2"],
"object": { nested: "value" }
}
}
};
export const networkFailureSimulations = {
// Différents types de timeouts
timeouts: [
{ delay: 100, succeed: true }, // Rapide
{ delay: 1000, succeed: true }, // Normal
{ delay: 5000, succeed: true }, // Lent
{ delay: 30000, succeed: false }, // Timeout
{ delay: 0, succeed: false } // Échec immédiat
],
// Codes d'erreur HTTP à tester
httpErrors: [
{ status: 400, message: "Bad Request" },
{ status: 401, message: "Unauthorized" },
{ status: 403, message: "Forbidden" },
{ status: 404, message: "Not Found" },
{ status: 408, message: "Request Timeout" },
{ status: 429, message: "Too Many Requests" },
{ status: 500, message: "Internal Server Error" },
{ status: 502, message: "Bad Gateway" },
{ status: 503, message: "Service Unavailable" },
{ status: 504, message: "Gateway Timeout" },
{ status: 520, message: "Unknown Error" },
{ status: 521, message: "Web Server Is Down" },
{ status: 522, message: "Connection Timed Out" },
{ status: 523, message: "Origin Is Unreachable" },
{ status: 524, message: "A Timeout Occurred" }
],
// Patterns de pannes réseau
networkPatterns: [
'intermittent', // Succès/échec alterné
'degrading', // Performance qui se dégrade
'recovering', // Récupération progressive
'cascade', // Échecs en cascade
'random' // Échecs aléatoires
]
};
export const browserCompatibilityTests = {
// APIs manquantes à simuler
missingAPIs: [
'fetch',
'crypto',
'crypto.subtle',
'URLSearchParams',
'localStorage',
'sessionStorage',
'console',
'JSON',
'Promise',
'setTimeout',
'clearTimeout'
],
// Différents User-Agents à tester
userAgents: [
// Desktop browsers
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59',
// Mobile browsers
'Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36',
'Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1',
// Older browsers
'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko', // IE11
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36', // Old Chrome
// Bots and tools
'curl/7.68.0',
'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)',
'PostmanRuntime/7.28.0',
'Googlebot/2.1 (+http://www.google.com/bot.html)'
],
// Différents Accept headers
acceptHeaders: [
'application/json',
'application/json, text/plain, */*',
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'*/*',
'application/json;charset=utf-8',
'text/plain',
'application/xml',
'text/html'
]
};
export const securityTestCases = {
// Tentatives d'injection de chemin
pathInjections: [
'../../../etc/passwd',
'..\\\\..\\\\..\\\\windows\\\\system32\\\\config\\\\sam',
'%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd',
'....//....//....//etc//passwd',
'\\\\x2e\\\\x2e\\\\x2f\\\\x2e\\\\x2e\\\\x2f\\\\x2e\\\\x2e\\\\x2fetc\\\\x2fpasswd',
'/proc/self/environ',
'/dev/null',
'CON', // Windows device name
'aux.txt', // Windows reserved name
'file:///etc/passwd',
'http://evil.com/malicious.json'
],
// Headers malveillants
maliciousHeaders: {
'X-Forwarded-For': '127.0.0.1, evil.com',
'Host': 'evil.com',
'Referer': 'http://evil.com/attack.html',
'User-Agent': '<script>alert("xss")</script>',
'X-Real-IP': ''; DROP TABLE users; --',
'Content-Length': '-1',
'Transfer-Encoding': 'chunked\\r\\nContent-Length: 0\\r\\n\\r\\n',
'X-Custom': 'A'.repeat(100000) // Header très long
},
// Requêtes malformées
malformedRequests: [
{ method: 'GET\\r\\nHost: evil.com' }, // HTTP splitting
{ method: 'GET HTTP/1.1\\r\\nHost: evil.com\\r\\n\\r\\nGET' }, // Request smuggling
{ url: '/do-proxy/test.json\\r\\nHost: evil.com' },
{ url: '/do-proxy/test.json?param=value&' + 'x'.repeat(10000) } // Query très longue
]
};
export const performanceTestData = {
// Différentes tailles de payload pour tester les performances
payloadSizes: [
{ name: 'tiny', size: 100 }, // 100 bytes
{ name: 'small', size: 1024 }, // 1KB
{ name: 'medium', size: 10240 }, // 10KB
{ name: 'large', size: 102400 }, // 100KB
{ name: 'huge', size: 1048576 } // 1MB
],
// Patterns de charge à tester
loadPatterns: [
{ name: 'constant', requests: 100, interval: 100 }, // Charge constante
{ name: 'burst', requests: 50, interval: 10 }, // Pics de charge
{ name: 'gradual', requests: 100, interval: 'ramp' }, // Montée progressive
{ name: 'spike', requests: 200, interval: 'random' } // Pics aléatoires
],
// Métriques à mesurer
metrics: [
'responseTime',
'throughput',
'errorRate',
'memoryUsage',
'cpuUsage',
'connectionCount'
]
};
export const concurrencyTestScenarios = [
{
name: 'Chargement simultané de modules identiques',
scenario: 'multiple_same_module',
concurrency: 10,
resource: 'sbs-level-7-8-new.json'
},
{
name: 'Chargement simultané de modules différents',
scenario: 'multiple_different_modules',
concurrency: 10,
resources: ['sbs-level-7-8-new.json', 'english-class-demo.json']
},
{
name: 'Création simultanée de jeux',
scenario: 'multiple_game_creation',
concurrency: 5,
gameTypes: ['whack-a-mole', 'memory-match', 'quiz-game']
},
{
name: 'Navigation rapide entre pages',
scenario: 'rapid_navigation',
concurrency: 3,
pages: ['home', 'games', 'levels', 'play']
},
{
name: 'Configuration simultanée',
scenario: 'concurrent_config_changes',
concurrency: 5,
operations: ['set', 'get', 'test_connection']
}
];
export const memoryLeakTestData = {
// Scénarios susceptibles de causer des fuites mémoire
scenarios: [
'repeated_module_loading',
'game_creation_destruction',
'config_changes',
'event_listener_attachment',
'timer_creation',
'fetch_operations'
],
// Tailles d'objets pour détecter les fuites
objectSizes: [
{ name: 'small', items: 100 },
{ name: 'medium', items: 1000 },
{ name: 'large', items: 10000 }
],
// Cycles à répéter pour détecter les fuites
cycles: 100
};
// Helper pour générer des données de test aléatoires
export function generateRandomContent(size = 'medium') {
const sizes = {
small: { vocab: 10, sentences: 5 },
medium: { vocab: 100, sentences: 20 },
large: { vocab: 1000, sentences: 100 }
};
const config = sizes[size] || sizes.medium;
const vocabulary = {};
const sentences = [];
// Générer du vocabulaire aléatoire
for (let i = 0; i < config.vocab; i++) {
vocabulary[`word${i}`] = `translation${i}`;
}
// Générer des phrases aléatoires
for (let i = 0; i < config.sentences; i++) {
sentences.push({
english: `English sentence ${i}`,
chinese: `中文句子 ${i}`,
prononciation: `pronunciation ${i}`
});
}
return {
name: `Random Content ${size}`,
vocabulary,
sentences
};
}
// Helper pour créer des erreurs réseau simulées
export function createNetworkErrorSimulator(pattern = 'random') {
let callCount = 0;
return () => {
callCount++;
switch (pattern) {
case 'intermittent':
return callCount % 2 === 0;
case 'degrading':
return Math.random() > (callCount * 0.1); // De plus en plus d'échecs
case 'recovering':
return Math.random() > Math.max(0.1, 0.9 - callCount * 0.1); // De moins en moins d'échecs
case 'cascade':
return callCount < 3; // Échecs en début puis récupération
case 'random':
default:
return Math.random() > 0.3; // 70% de succès
}
};
}