610 lines
21 KiB
HTML
610 lines
21 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Library Manager Test Suite</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
background: #1a1a1a;
|
||
color: #e0e0e0;
|
||
padding: 20px;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.container {
|
||
max-width: 1400px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
h1 {
|
||
text-align: center;
|
||
color: #ff006e;
|
||
margin-bottom: 30px;
|
||
font-size: 2.5em;
|
||
}
|
||
|
||
.test-section {
|
||
background: #2a2a2a;
|
||
border-radius: 10px;
|
||
padding: 20px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.test-section h2 {
|
||
color: #8338ec;
|
||
margin-bottom: 15px;
|
||
font-size: 1.5em;
|
||
}
|
||
|
||
.test-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||
gap: 10px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.test-result {
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
background: #1a1a1a;
|
||
border-left: 4px solid #666;
|
||
}
|
||
|
||
.test-result.pass {
|
||
border-left-color: #00ff88;
|
||
background: rgba(0, 255, 136, 0.1);
|
||
}
|
||
|
||
.test-result.fail {
|
||
border-left-color: #ff006e;
|
||
background: rgba(255, 0, 110, 0.1);
|
||
}
|
||
|
||
.test-result h3 {
|
||
font-size: 1em;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.test-result.pass h3 { color: #00ff88; }
|
||
.test-result.fail h3 { color: #ff006e; }
|
||
|
||
.test-result p {
|
||
font-size: 0.9em;
|
||
color: #aaa;
|
||
}
|
||
|
||
.button-group {
|
||
display: flex;
|
||
gap: 10px;
|
||
flex-wrap: wrap;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
button {
|
||
padding: 12px 24px;
|
||
border: none;
|
||
border-radius: 8px;
|
||
background: linear-gradient(135deg, #ff006e, #8338ec);
|
||
color: white;
|
||
font-weight: bold;
|
||
cursor: pointer;
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
button:hover {
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
button:active {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
.status-box {
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
margin-bottom: 20px;
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 0.9em;
|
||
}
|
||
|
||
.status-box.success {
|
||
background: rgba(0, 255, 136, 0.1);
|
||
border: 1px solid #00ff88;
|
||
color: #00ff88;
|
||
}
|
||
|
||
.status-box.error {
|
||
background: rgba(255, 0, 110, 0.1);
|
||
border: 1px solid #ff006e;
|
||
color: #ff006e;
|
||
}
|
||
|
||
.status-box.info {
|
||
background: rgba(131, 56, 236, 0.1);
|
||
border: 1px solid #8338ec;
|
||
color: #8338ec;
|
||
}
|
||
|
||
.json-display {
|
||
background: #0a0a0a;
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
white-space: pre-wrap;
|
||
word-wrap: break-word;
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 0.85em;
|
||
max-height: 400px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.media-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||
gap: 15px;
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.media-card {
|
||
background: #1a1a1a;
|
||
border-radius: 8px;
|
||
padding: 15px;
|
||
border: 1px solid #333;
|
||
}
|
||
|
||
.media-card h4 {
|
||
color: #ff006e;
|
||
font-size: 0.9em;
|
||
margin-bottom: 10px;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.tag-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 5px;
|
||
margin: 10px 0;
|
||
}
|
||
|
||
.tag {
|
||
background: rgba(131, 56, 236, 0.3);
|
||
padding: 3px 8px;
|
||
border-radius: 4px;
|
||
font-size: 0.75em;
|
||
color: #8338ec;
|
||
}
|
||
|
||
.rating {
|
||
color: #ffb700;
|
||
font-size: 0.9em;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<h1>📚 Library Manager Test Suite</h1>
|
||
|
||
<!-- Automated Tests Section -->
|
||
<div class="test-section">
|
||
<h2>Automated Tests</h2>
|
||
<button onclick="runAllTests()">🧪 Run All Tests</button>
|
||
<div id="test-results" class="test-grid"></div>
|
||
</div>
|
||
|
||
<!-- Manual Testing Section -->
|
||
<div class="test-section">
|
||
<h2>Manual Testing</h2>
|
||
<div class="button-group">
|
||
<button onclick="syncWithLibrary()">🔄 Sync with Existing Library</button>
|
||
<button onclick="addSampleMedia()">➕ Add Sample Media (Test Only)</button>
|
||
<button onclick="testBulkTagging()">🏷️ Test Bulk Tagging</button>
|
||
<button onclick="testSearch()">🔍 Test Search</button>
|
||
<button onclick="testRatings()">⭐ Test Ratings</button>
|
||
<button onclick="testCollections()">📁 Test Collections</button>
|
||
<button onclick="showStats()">📈 Show Stats</button>
|
||
<button onclick="showAllMedia()">📚 Show All Media</button>
|
||
<button onclick="resetLibrary()">🔄 Reset Library</button>
|
||
</div>
|
||
<div id="manual-output"></div>
|
||
</div>
|
||
|
||
<!-- Library Display -->
|
||
<div class="test-section">
|
||
<h2>Current Library State</h2>
|
||
<div id="library-display" class="json-display"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Load Dependencies -->
|
||
<script src="src/data/gameData.js"></script>
|
||
<script src="src/features/academy/libraryManager.js"></script>
|
||
|
||
<script>
|
||
// Test runner
|
||
function runAllTests() {
|
||
const tests = [
|
||
testInitialization,
|
||
testAddMedia,
|
||
testTagging,
|
||
testBulkTagging,
|
||
testRating,
|
||
testFavorites,
|
||
testSearch,
|
||
testCollections,
|
||
testStats,
|
||
testPersistence
|
||
];
|
||
|
||
const resultsDiv = document.getElementById('test-results');
|
||
resultsDiv.innerHTML = '';
|
||
|
||
tests.forEach(test => {
|
||
const result = test();
|
||
const resultDiv = document.createElement('div');
|
||
resultDiv.className = `test-result ${result.pass ? 'pass' : 'fail'}`;
|
||
resultDiv.innerHTML = `
|
||
<h3>${result.pass ? '✓' : '✗'} ${result.name}</h3>
|
||
<p>${result.message}</p>
|
||
`;
|
||
resultsDiv.appendChild(resultDiv);
|
||
});
|
||
}
|
||
|
||
// Test 1: Initialization
|
||
function testInitialization() {
|
||
const library = window.libraryManager.getLibrary();
|
||
const hasRequiredFields = library.media && library.tags && library.collections;
|
||
|
||
return {
|
||
name: 'Initialization Test',
|
||
pass: hasRequiredFields && library.version === 1,
|
||
message: hasRequiredFields ? 'Library initialized with all required structures' : 'Missing fields'
|
||
};
|
||
}
|
||
|
||
// Test 2: Add Media
|
||
function testAddMedia() {
|
||
const success = window.libraryManager.addMediaItem('assets/test/video1.mp4', {
|
||
tags: ['edging', 'pov', 'hd'],
|
||
rating: 4
|
||
});
|
||
|
||
const library = window.libraryManager.getLibrary();
|
||
const item = library.media['assets/test/video1.mp4'];
|
||
|
||
return {
|
||
name: 'Add Media Test',
|
||
pass: success && item && item.tags.length === 3,
|
||
message: success ? 'Media item added with tags and rating' : 'Failed to add media'
|
||
};
|
||
}
|
||
|
||
// Test 3: Tagging
|
||
function testTagging() {
|
||
window.libraryManager.addMediaItem('assets/test/video2.mp4');
|
||
window.libraryManager.addTags('assets/test/video2.mp4', ['femdom', 'worship']);
|
||
|
||
const library = window.libraryManager.getLibrary();
|
||
const item = library.media['assets/test/video2.mp4'];
|
||
|
||
return {
|
||
name: 'Tagging Test',
|
||
pass: item.tags.includes('femdom') && item.tags.includes('worship'),
|
||
message: 'Tags added successfully'
|
||
};
|
||
}
|
||
|
||
// Test 4: Bulk Tagging
|
||
function testBulkTagging() {
|
||
const files = ['assets/test/video3.mp4', 'assets/test/video4.mp4', 'assets/test/video5.mp4'];
|
||
const result = window.libraryManager.bulkAddTags(files, ['compilation', 'pmv']);
|
||
|
||
return {
|
||
name: 'Bulk Tagging Test',
|
||
pass: result.filesTagged === 3,
|
||
message: `Bulk tagged ${result.filesTagged} files with ${result.tags.length} tags`
|
||
};
|
||
}
|
||
|
||
// Test 5: Rating
|
||
function testRating() {
|
||
window.libraryManager.setRating('assets/test/video1.mp4', 5);
|
||
const library = window.libraryManager.getLibrary();
|
||
const rating = library.media['assets/test/video1.mp4'].rating;
|
||
|
||
return {
|
||
name: 'Rating Test',
|
||
pass: rating === 5,
|
||
message: `Rating set to ${rating}/5`
|
||
};
|
||
}
|
||
|
||
// Test 6: Favorites
|
||
function testFavorites() {
|
||
window.libraryManager.addToFavorites('assets/test/video1.mp4');
|
||
const library = window.libraryManager.getLibrary();
|
||
|
||
return {
|
||
name: 'Favorites Test',
|
||
pass: library.favorites.includes('assets/test/video1.mp4'),
|
||
message: 'Item added to favorites'
|
||
};
|
||
}
|
||
|
||
// Test 7: Search
|
||
function testSearch() {
|
||
const results = window.libraryManager.searchMedia({
|
||
anyTags: ['edging', 'femdom'],
|
||
minRating: 3
|
||
});
|
||
|
||
return {
|
||
name: 'Search Test',
|
||
pass: results.length > 0,
|
||
message: `Found ${results.length} items matching search criteria`
|
||
};
|
||
}
|
||
|
||
// Test 8: Collections
|
||
function testCollections() {
|
||
window.libraryManager.createCollection('My Playlist', [
|
||
'assets/test/video1.mp4',
|
||
'assets/test/video2.mp4'
|
||
]);
|
||
|
||
const items = window.libraryManager.getCollection('My Playlist');
|
||
|
||
return {
|
||
name: 'Collections Test',
|
||
pass: items.length === 2,
|
||
message: `Collection created with ${items.length} items`
|
||
};
|
||
}
|
||
|
||
// Test 9: Stats
|
||
function testStats() {
|
||
const stats = window.libraryManager.getLibraryStats();
|
||
|
||
return {
|
||
name: 'Statistics Test',
|
||
pass: stats.totalItems > 0 && stats.hasOwnProperty('averageRating'),
|
||
message: `${stats.totalItems} items, ${stats.taggedItems} tagged, avg rating ${stats.averageRating}`
|
||
};
|
||
}
|
||
|
||
// Test 10: Persistence
|
||
function testPersistence() {
|
||
window.libraryManager.addMediaItem('assets/test/persistence.mp4', { rating: 3 });
|
||
|
||
const savedData = JSON.parse(localStorage.getItem('webGame-data'));
|
||
const exists = savedData.academyLibrary.media['assets/test/persistence.mp4'] !== undefined;
|
||
|
||
return {
|
||
name: 'Persistence Test',
|
||
pass: exists,
|
||
message: exists ? 'Library persists to localStorage' : 'Persistence failed'
|
||
};
|
||
}
|
||
|
||
// Manual testing functions
|
||
function syncWithLibrary() {
|
||
const result = window.libraryManager.syncWithExistingLibrary();
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box success">
|
||
✅ Synced with existing library:<br>
|
||
- Total videos: ${result.total}<br>
|
||
- New videos: ${result.new}<br>
|
||
- Existing videos: ${result.existing}
|
||
</div>`;
|
||
|
||
// Show the media
|
||
showAllMedia();
|
||
}
|
||
|
||
function addSampleMedia() {
|
||
const sampleFiles = [
|
||
{ path: 'assets/pornstars/riley-reid-1.mp4', tags: ['solo', 'pov', 'professional'], rating: 5 },
|
||
{ path: 'assets/pornstars/mia-khalifa-2.mp4', tags: ['group', 'hd', 'hardcore'], rating: 4 },
|
||
{ path: 'assets/feet/footjob-1.mp4', tags: ['feet', 'pov', 'fetish'], rating: 4 },
|
||
{ path: 'assets/hentai/anime-1.mp4', tags: ['hentai', 'animated', 'mindbreak'], rating: 3 },
|
||
{ path: 'assets/BBC/interracial-1.mp4', tags: ['bbc', 'couples', 'intense'], rating: 5 }
|
||
];
|
||
|
||
sampleFiles.forEach(file => {
|
||
window.libraryManager.addMediaItem(file.path, {
|
||
tags: file.tags,
|
||
rating: file.rating
|
||
});
|
||
});
|
||
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box success">
|
||
Added ${sampleFiles.length} sample media items to library
|
||
</div>`;
|
||
|
||
showAllMedia();
|
||
}
|
||
|
||
function testBulkTagging() {
|
||
const library = window.libraryManager.getLibrary();
|
||
const allFiles = Object.keys(library.media);
|
||
|
||
if (allFiles.length === 0) {
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box error">No media in library. Add sample media first.</div>`;
|
||
return;
|
||
}
|
||
|
||
const result = window.libraryManager.bulkAddTags(allFiles.slice(0, 3), ['test-tag', 'bulk-tagged']);
|
||
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box success">
|
||
Bulk tagged ${result.filesTagged} files with tags: ${result.tags.join(', ')}
|
||
</div>`;
|
||
}
|
||
|
||
function testSearch() {
|
||
const results = window.libraryManager.searchMedia({
|
||
anyTags: ['pov', 'solo'],
|
||
minRating: 3,
|
||
sortBy: 'rating',
|
||
limit: 5
|
||
});
|
||
|
||
const outputDiv = document.getElementById('manual-output');
|
||
|
||
if (results.length === 0) {
|
||
outputDiv.innerHTML = `<div class="status-box error">No results found. Add sample media first.</div>`;
|
||
return;
|
||
}
|
||
|
||
let html = `<div class="status-box success">Found ${results.length} items</div>`;
|
||
html += '<div class="media-grid">';
|
||
|
||
results.forEach(item => {
|
||
html += `
|
||
<div class="media-card">
|
||
<h4>${item.filePath.split('/').pop()}</h4>
|
||
<div class="rating">⭐ ${item.rating}/5</div>
|
||
<div class="tag-list">
|
||
${item.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
html += '</div>';
|
||
outputDiv.innerHTML = html;
|
||
}
|
||
|
||
function testRatings() {
|
||
const library = window.libraryManager.getLibrary();
|
||
const allFiles = Object.keys(library.media);
|
||
|
||
if (allFiles.length === 0) {
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box error">No media in library. Add sample media first.</div>`;
|
||
return;
|
||
}
|
||
|
||
// Set random ratings
|
||
allFiles.forEach(file => {
|
||
window.libraryManager.setRating(file, Math.floor(Math.random() * 5) + 1);
|
||
});
|
||
|
||
const stats = window.libraryManager.getLibraryStats();
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box success">
|
||
Rated ${stats.ratedItems} items<br>
|
||
Average rating: ${stats.averageRating}/5
|
||
</div>`;
|
||
}
|
||
|
||
function testCollections() {
|
||
const library = window.libraryManager.getLibrary();
|
||
const allFiles = Object.keys(library.media);
|
||
|
||
if (allFiles.length < 3) {
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box error">Need at least 3 items. Add sample media first.</div>`;
|
||
return;
|
||
}
|
||
|
||
window.libraryManager.createCollection('Test Collection', allFiles.slice(0, 3));
|
||
const items = window.libraryManager.getCollection('Test Collection');
|
||
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box success">
|
||
Created collection with ${items.length} items
|
||
</div>`;
|
||
}
|
||
|
||
function showStats() {
|
||
const stats = window.libraryManager.getLibraryStats();
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box info">Library Statistics:</div>` +
|
||
`<div class="json-display">${JSON.stringify(stats, null, 2)}</div>`;
|
||
}
|
||
|
||
function showAllMedia() {
|
||
const library = window.libraryManager.getLibrary();
|
||
const allMedia = Object.values(library.media);
|
||
|
||
if (allMedia.length === 0) {
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box info">Library is empty. Add some media items.</div>`;
|
||
return;
|
||
}
|
||
|
||
const outputDiv = document.getElementById('manual-output');
|
||
let html = `<div class="status-box info">Total items: ${allMedia.length}</div>`;
|
||
html += '<div class="media-grid">';
|
||
|
||
allMedia.forEach(item => {
|
||
html += `
|
||
<div class="media-card">
|
||
<h4>${item.filePath.split('/').pop()}</h4>
|
||
<div class="rating">⭐ ${item.rating}/5</div>
|
||
<div class="tag-list">
|
||
${item.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
|
||
</div>
|
||
<div style="margin-top: 8px; font-size: 0.8em; color: #888;">
|
||
Plays: ${item.timesPlayed || 0}
|
||
</div>
|
||
</div>
|
||
`;
|
||
});
|
||
|
||
html += '</div>';
|
||
outputDiv.innerHTML = html;
|
||
}
|
||
|
||
function resetLibrary() {
|
||
if (confirm('Reset entire library? This will delete all media items and tags.')) {
|
||
window.libraryManager.resetLibrary();
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box success">Library reset to empty state</div>`;
|
||
updateLibraryDisplay();
|
||
}
|
||
}
|
||
|
||
function updateLibraryDisplay() {
|
||
const library = window.libraryManager.getLibrary();
|
||
document.getElementById('library-display').textContent = JSON.stringify(library, null, 2);
|
||
}
|
||
|
||
// Initialize on load
|
||
window.addEventListener('DOMContentLoaded', () => {
|
||
updateLibraryDisplay();
|
||
|
||
// Auto-sync with existing library if available
|
||
if (window.desktopFileManager) {
|
||
setTimeout(() => {
|
||
const result = window.libraryManager.syncWithExistingLibrary();
|
||
if (result.total > 0) {
|
||
const outputDiv = document.getElementById('manual-output');
|
||
outputDiv.innerHTML = `<div class="status-box info">
|
||
📹 Auto-synced ${result.total} videos from existing library.
|
||
Use "🔄 Sync with Existing Library" to refresh.
|
||
</div>`;
|
||
}
|
||
}, 1000);
|
||
}
|
||
|
||
// Auto-refresh progress display every 2 seconds
|
||
setInterval(updateLibraryDisplay, 2000);
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|