100 lines
4.5 KiB
JavaScript
100 lines
4.5 KiB
JavaScript
/**
|
|
* ICD Test Runner — CRUD: Profile & Settings
|
|
* Profile update, settings merge round-trip, avatar lifecycle.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
var T = window.ICD;
|
|
if (!T) return;
|
|
if (!T.crud) T.crud = {};
|
|
|
|
T.crud.profile = async function (testTag) {
|
|
|
|
// ── GET /profile — full shape (augments smoke) ──
|
|
var originalProfile = null;
|
|
await T.test('crud', 'profile', 'GET /profile (full shape)', async function () {
|
|
var d = await T.apiGet('/profile');
|
|
T.assertShape(d, T.S.profile, 'profile');
|
|
T.assert(typeof d.email === 'string' && d.email.length > 0, 'email must be non-empty string');
|
|
T.assert(typeof d.settings === 'object' && d.settings !== null, 'settings must be object (not null)');
|
|
originalProfile = d;
|
|
});
|
|
|
|
// ── PUT /profile — update display_name ──
|
|
if (originalProfile) {
|
|
await T.test('crud', 'profile', 'PUT /profile (display_name)', async function () {
|
|
var newName = testTag + '-display';
|
|
var d = await T.apiPut('/profile', { display_name: newName });
|
|
T.assertShape(d, T.S.profile, 'profile-after-update');
|
|
T.assert(d.display_name === newName, 'display_name not updated: ' + d.display_name);
|
|
});
|
|
|
|
// Restore original display_name
|
|
await T.test('crud', 'profile', 'PUT /profile (restore display_name)', async function () {
|
|
var d = await T.apiPut('/profile', { display_name: originalProfile.display_name || '' });
|
|
T.assertShape(d, T.S.profile, 'profile-restored');
|
|
});
|
|
}
|
|
|
|
// ── GET /settings — envelope with empty object for clean user ──
|
|
await T.test('crud', 'profile', 'GET /settings (envelope)', async function () {
|
|
var d = await T.apiGet('/settings');
|
|
T.assertHasKey(d, 'settings', 'GET /settings');
|
|
T.assert(typeof d.settings === 'object' && d.settings !== null, 'settings must be object');
|
|
});
|
|
|
|
// ── PUT /settings — create, then merge, then verify ──
|
|
await T.test('crud', 'profile', 'PUT /settings (initial)', async function () {
|
|
var d = await T.apiPut('/settings', {
|
|
icd_test_key: 'alpha',
|
|
icd_test_other: 'keep-me'
|
|
});
|
|
T.assertHasKey(d, 'settings', 'PUT /settings response');
|
|
T.assert(d.settings.icd_test_key === 'alpha', 'icd_test_key should be alpha');
|
|
T.assert(d.settings.icd_test_other === 'keep-me', 'icd_test_other should be set');
|
|
});
|
|
|
|
await T.test('crud', 'profile', 'PUT /settings (merge overwrites + preserves)', async function () {
|
|
var d = await T.apiPut('/settings', { icd_test_key: 'beta' });
|
|
T.assertHasKey(d, 'settings', 'PUT /settings merge');
|
|
T.assert(d.settings.icd_test_key === 'beta', 'icd_test_key should be overwritten to beta');
|
|
T.assert(d.settings.icd_test_other === 'keep-me', 'icd_test_other should be preserved');
|
|
});
|
|
|
|
await T.test('crud', 'profile', 'GET /settings (round-trip verify)', async function () {
|
|
var d = await T.apiGet('/settings');
|
|
T.assert(d.settings.icd_test_key === 'beta', 'GET round-trip: icd_test_key should be beta');
|
|
T.assert(d.settings.icd_test_other === 'keep-me', 'GET round-trip: icd_test_other preserved');
|
|
});
|
|
|
|
// ── Avatar lifecycle: upload → verify in profile → delete → verify gone ──
|
|
// Build a minimal 1x1 red PNG as base64
|
|
var tinyPNG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==';
|
|
|
|
await T.test('crud', 'profile', 'POST /profile/avatar (upload)', async function () {
|
|
var d = await T.apiPost('/profile/avatar', { image: tinyPNG });
|
|
T.assertHasKey(d, 'avatar', 'avatar-upload');
|
|
T.assert(typeof d.avatar === 'string' && d.avatar.indexOf('data:image/png') === 0, 'avatar should be data URI');
|
|
});
|
|
|
|
await T.test('crud', 'profile', 'GET /profile (avatar present)', async function () {
|
|
var d = await T.apiGet('/profile');
|
|
T.assert(d.avatar && typeof d.avatar === 'string', 'profile should have avatar after upload');
|
|
});
|
|
|
|
await T.test('crud', 'profile', 'DELETE /profile/avatar', async function () {
|
|
await T.safeDelete('/profile/avatar');
|
|
});
|
|
|
|
await T.test('crud', 'profile', 'GET /profile (avatar cleared)', async function () {
|
|
var d = await T.apiGet('/profile');
|
|
T.assert(!d.avatar, 'avatar should be null/absent after delete');
|
|
});
|
|
|
|
// ── Clean up test settings keys ──
|
|
// Overwrite with empty values — there's no DELETE for individual keys
|
|
// so just leave them; they're namespaced with icd_test_ prefix.
|
|
|
|
};
|
|
})();
|