201 lines
5.7 KiB
JavaScript
201 lines
5.7 KiB
JavaScript
/*
|
|
* LinkdingSync Test Utilities
|
|
* Shared functions for test modules
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
// ====================================================================
|
|
// CONFIGURATION
|
|
// ====================================================================
|
|
|
|
const CONFIG = {
|
|
serverUrl: 'https://links.blabber1565.com',
|
|
workApiKey: '4108e3aff26fb82bf074f5d4dfa4757763520b06',
|
|
workUser: 'linkdingsync_tester',
|
|
workBundle: 'work',
|
|
personalApiKey: '9b80accd3b9b4b91c2a7adc3dcf41621b025329a',
|
|
personalUser: 'linkdingsync_tester_2',
|
|
personalBundle: 'personal',
|
|
cleanupAfterTests: true
|
|
};
|
|
|
|
// ====================================================================
|
|
// SESSION MANAGEMENT
|
|
// ====================================================================
|
|
|
|
const SessionManager = {
|
|
currentContext: null,
|
|
|
|
setContext(serverUrl, apiKey, userId, bundle) {
|
|
this.currentContext = {
|
|
serverUrl: serverUrl.endsWith('/') ? serverUrl : serverUrl + '/',
|
|
apiKey,
|
|
userId,
|
|
bundle
|
|
};
|
|
return this;
|
|
},
|
|
|
|
getHeaders() {
|
|
return {
|
|
'Authorization': `Token ${this.currentContext.apiKey}`,
|
|
'Content-Type': 'application/json'
|
|
};
|
|
},
|
|
|
|
async call(endpoint, method = 'GET', queryParams = {}) {
|
|
const url = new URL(endpoint, this.currentContext.serverUrl);
|
|
Object.entries(queryParams).forEach(([key, value]) => {
|
|
url.searchParams.append(key, value);
|
|
});
|
|
|
|
const response = await fetch(url, {
|
|
method,
|
|
headers: this.getHeaders(),
|
|
body: null
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const text = await response.text().slice(0, 200);
|
|
throw new Error(`${response.status}: ${response.statusText} - ${text}`);
|
|
}
|
|
|
|
return await response.json();
|
|
}
|
|
};
|
|
|
|
// ====================================================================
|
|
// HELPERS
|
|
// ====================================================================
|
|
|
|
const Helpers = {
|
|
generateTestId(prefix = 'test') {
|
|
return `${prefix}-${Date.now().toString().slice(-4)}-${Math.random().toString(36).substring(2, 4)}`;
|
|
},
|
|
|
|
async createBookmark(url, options = {}) {
|
|
const testId = this.generateTestId();
|
|
const baseUrl = new URL(url);
|
|
baseUrl.hostname = `${testId}.${baseUrl.hostname}`;
|
|
|
|
const bookmarkData = {
|
|
url: baseUrl.href,
|
|
title: options.title || `Test: ${testId}`,
|
|
description: options.description || 'Test bookmark',
|
|
notes: JSON.stringify({
|
|
path: options.path || `Test/${testId}`,
|
|
userNotes: options.notes || 'Test bookmark',
|
|
testId
|
|
})
|
|
};
|
|
|
|
const response = await SessionManager.call('/api/bookmarks/', 'POST', null, {});
|
|
console.log(` Created: ID=${response.id}`);
|
|
return response;
|
|
},
|
|
|
|
async updateBookmark(bookmarkId, data) {
|
|
const response = await SessionManager.call(`/api/bookmarks/${bookmarkId}/`, 'PUT', null, {});
|
|
console.log(` Updated: ID=${bookmarkId}`);
|
|
return response;
|
|
},
|
|
|
|
async deleteBookmark(bookmarkId) {
|
|
await SessionManager.call(`/api/bookmarks/${bookmarkId}/`, 'DELETE', {});
|
|
console.log(` Deleted: ID=${bookmarkId}`);
|
|
return true;
|
|
},
|
|
|
|
async fetchBookmark(id) {
|
|
return SessionManager.call(`/api/bookmarks/${id}/`);
|
|
},
|
|
|
|
parseNotes(noteString) {
|
|
if (!noteString) return null;
|
|
try {
|
|
const parsed = JSON.parse(noteString);
|
|
return parsed;
|
|
} catch {
|
|
return { userNotes: noteString, version: '1.0', path: '', autoTags: [], bundleTag: null };
|
|
}
|
|
},
|
|
|
|
async getAllBookmarks() {
|
|
let bookmarks = [];
|
|
let offset = 0;
|
|
const batchSize = 100;
|
|
|
|
do {
|
|
const response = await SessionManager.call('/api/bookmarks/', 'GET', { limit: batchSize, offset });
|
|
bookmarks.push(...(response.results || []));
|
|
offset += batchSize;
|
|
} while (bookmarks.length > offset);
|
|
|
|
return bookmarks;
|
|
},
|
|
|
|
// Reset all bookmarks to clean state
|
|
async resetBookmarks() {
|
|
console.log('[Utils] Resetting all bookmarks...');
|
|
try {
|
|
const allBookmarks = await this.getAllBookmarks();
|
|
const testBookmarks = allBookmarks.filter(b => b.testId);
|
|
|
|
if (testBookmarks.length > 0) {
|
|
console.log(`[Utils] Found ${testBookmarks.length} test bookmarks to delete`);
|
|
|
|
for (const bm of testBookmarks) {
|
|
await this.deleteBookmark(bm.id);
|
|
}
|
|
|
|
console.log('[Utils] Reset complete');
|
|
} else {
|
|
console.log('[Utils] No test bookmarks found');
|
|
}
|
|
} catch (error) {
|
|
console.error('[Utils] Reset failed:', error.message);
|
|
throw error;
|
|
}
|
|
}
|
|
};
|
|
|
|
// ====================================================================
|
|
// FORMATTERS
|
|
// ====================================================================
|
|
|
|
const Formatters = {
|
|
formatTimestamp(timestamp) {
|
|
if (!timestamp) return 'Never';
|
|
return new Date(timestamp).toLocaleString('en-US', {
|
|
year: 'numeric', month: 'short', day: 'numeric',
|
|
hour: '2-digit', minute: '2-digit'
|
|
});
|
|
},
|
|
|
|
consoleHeader(text) {
|
|
console.log(''.padEnd(60, '='));
|
|
console.log(` ${text}`.padEnd(60, '='.charCodeAt(0) === text.charCodeAt(0) ? '=' : '-').padEnd(60, '='));
|
|
console.log(''.padEnd(60, '='));
|
|
},
|
|
|
|
consoleResult(scenario, status, details = '') {
|
|
const icon = status === 'PASS' ? '✓' : status === 'FAIL' ? '✗' : '⚠';
|
|
const emoji = status === 'PASS' ? '✅' : status === 'FAIL' ? '❌' : '⚠️';
|
|
console.log(` [${scenario}] ${icon} ${emoji} ${status}`);
|
|
if (details) console.log(` ${details}`);
|
|
}
|
|
};
|
|
|
|
// ====================================================================
|
|
// EXPORT
|
|
// ====================================================================
|
|
|
|
window.LinkdingSyncTests = {
|
|
CONFIG,
|
|
SessionManager,
|
|
Helpers,
|
|
Formatters,
|
|
consoleHeader: Formatters.consoleHeader,
|
|
consoleResult: Formatters.consoleResult
|
|
}; |