Files
bitvid/tests/ui/profile-modal-moderation-settings.test.mjs
T

311 lines
9.6 KiB
JavaScript

import test, { beforeEach, afterEach } from "node:test";
import assert from "node:assert/strict";
import { JSDOM } from "jsdom";
import ProfileModalController from "../../js/ui/profileModalController.js";
const TEMPLATE_HTML = `
<div id="profileModal">
<div class="bv-modal__panel"></div>
<div class="bv-modal-backdrop"></div>
<div data-profile-layout>
<div data-profile-mobile-menu></div>
<div data-profile-mobile-pane></div>
</div>
<button id="closeProfileModal" type="button"></button>
<button id="profileModalBack" type="button"></button>
<button id="profileLogoutBtn" type="button"></button>
<a id="profileChannelLink" href="#"></a>
<button id="profileAddAccountBtn" type="button"></button>
<div id="profileNavAccount"></div>
<div id="profilePaneAccount"></div>
<div id="profileModerationSettings">
<input id="profileModerationBlurThreshold" type="number" />
<input id="profileModerationAutoplayThreshold" type="number" />
<div data-role="trusted-hide-controls">
<input id="profileModerationMuteHideThreshold" type="number" />
<input id="profileModerationSpamHideThreshold" type="number" />
</div>
<button id="profileModerationSave" type="button">Save</button>
<button id="profileModerationReset" type="button">Reset</button>
<p id="profileModerationStatus"></p>
</div>
</div>
`;
let dom;
let documentRef;
let windowRef;
let controller;
let storedSettings;
let moderationService;
let callbackPayloads;
beforeEach(async () => {
dom = new JSDOM("<!DOCTYPE html><html><body></body></html>", {
pretendToBeVisual: true,
url: "https://example.com",
});
windowRef = dom.window;
documentRef = windowRef.document;
global.window = windowRef;
global.document = documentRef;
global.HTMLElement = windowRef.HTMLElement;
global.HTMLInputElement = windowRef.HTMLInputElement;
global.Event = windowRef.Event;
global.fetch = async (url) => {
assert.equal(url, "components/profile-modal.html");
return {
ok: true,
async text() {
return TEMPLATE_HTML;
},
};
};
storedSettings = {
blurThreshold: 3,
autoplayBlockThreshold: 2,
trustedMuteHideThreshold: 1,
trustedSpamHideThreshold: 3,
};
moderationService = {
getDefaultModerationSettings() {
return {
blurThreshold: 3,
autoplayBlockThreshold: 2,
trustedMuteHideThreshold: 1,
trustedSpamHideThreshold: 3,
};
},
getActiveModerationSettings() {
return { ...storedSettings };
},
updateModerationSettings(partial = {}) {
if (Object.prototype.hasOwnProperty.call(partial, "blurThreshold")) {
const value = partial.blurThreshold;
storedSettings.blurThreshold = value === null ? 3 : value;
}
if (
Object.prototype.hasOwnProperty.call(
partial,
"autoplayBlockThreshold",
)
) {
const value = partial.autoplayBlockThreshold;
storedSettings.autoplayBlockThreshold = value === null ? 2 : value;
}
if (
Object.prototype.hasOwnProperty.call(
partial,
"trustedMuteHideThreshold",
)
) {
const value = partial.trustedMuteHideThreshold;
storedSettings.trustedMuteHideThreshold = value === null ? 1 : value;
}
if (
Object.prototype.hasOwnProperty.call(
partial,
"trustedSpamHideThreshold",
)
) {
const value = partial.trustedSpamHideThreshold;
storedSettings.trustedSpamHideThreshold = value === null ? 3 : value;
}
return { ...storedSettings };
},
resetModerationSettings() {
storedSettings = {
blurThreshold: 3,
autoplayBlockThreshold: 2,
trustedMuteHideThreshold: 1,
trustedSpamHideThreshold: 3,
};
return { ...storedSettings };
},
};
callbackPayloads = [];
controller = new ProfileModalController({
modalContainer: documentRef.body,
removeTrackingScripts: () => {},
services: {
relayManager: {},
userBlocks: {},
nostrClient: {},
accessControl: {},
getCurrentUserNpub: () => null,
moderationSettings: moderationService,
loadVideos: async () => undefined,
onVideosShouldRefresh: async () => undefined,
onAccessControlUpdated: async () => undefined,
persistSavedProfiles: () => {},
watchHistoryService: {},
authService: {},
log: () => {},
closeAllMoreMenus: () => {},
},
state: {
getSavedProfiles: () => [],
setSavedProfiles: () => ({ changed: false, profiles: [] }),
persistSavedProfiles: () => {},
getActivePubkey: () => null,
setActivePubkey: () => null,
},
callbacks: {
onModerationSettingsChange: (payload) => callbackPayloads.push(payload),
},
});
});
afterEach(() => {
if (dom) {
dom.window.close();
}
dom = null;
documentRef = null;
windowRef = null;
controller = null;
storedSettings = null;
moderationService = null;
callbackPayloads = null;
delete global.window;
delete global.document;
delete global.HTMLElement;
delete global.HTMLInputElement;
delete global.Event;
delete global.fetch;
});
test("moderation settings save updates service and disables control", async () => {
await controller.load();
assert.equal(controller.moderationBlurInput.value, "3");
assert.equal(controller.moderationAutoplayInput.value, "2");
assert.equal(controller.moderationMuteHideInput.value, "1");
assert.equal(controller.moderationSpamHideInput.value, "3");
assert.equal(controller.moderationSaveButton.disabled, true);
controller.moderationBlurInput.value = "5";
controller.moderationBlurInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
controller.moderationAutoplayInput.value = "4";
controller.moderationAutoplayInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
controller.moderationMuteHideInput.value = "2";
controller.moderationMuteHideInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
controller.moderationSpamHideInput.value = "6";
controller.moderationSpamHideInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
assert.equal(controller.moderationSaveButton.disabled, false);
const result = await controller.handleModerationSettingsSave();
assert.equal(result.success, true);
assert.deepEqual(storedSettings, {
blurThreshold: 5,
autoplayBlockThreshold: 4,
trustedMuteHideThreshold: 2,
trustedSpamHideThreshold: 6,
});
assert.equal(controller.moderationSaveButton.disabled, true);
assert.equal(
controller.moderationStatusText.textContent,
"Moderation settings saved.",
);
assert.equal(callbackPayloads.length, 1);
assert.deepEqual(callbackPayloads[0].settings, {
blurThreshold: 5,
autoplayBlockThreshold: 4,
trustedMuteHideThreshold: 2,
trustedSpamHideThreshold: 6,
});
});
test("moderation reset restores defaults and clearing inputs uses defaults", async () => {
storedSettings = {
blurThreshold: 6,
autoplayBlockThreshold: 4,
trustedMuteHideThreshold: 3,
trustedSpamHideThreshold: 5,
};
await controller.load();
assert.equal(controller.moderationBlurInput.value, "6");
assert.equal(controller.moderationAutoplayInput.value, "4");
assert.equal(controller.moderationMuteHideInput.value, "3");
assert.equal(controller.moderationSpamHideInput.value, "5");
const resetContext = await controller.handleModerationSettingsReset();
assert.equal(resetContext.success, true);
assert.deepEqual(storedSettings, {
blurThreshold: 3,
autoplayBlockThreshold: 2,
trustedMuteHideThreshold: 1,
trustedSpamHideThreshold: 3,
});
assert.equal(controller.moderationBlurInput.value, "3");
assert.equal(controller.moderationAutoplayInput.value, "2");
assert.equal(controller.moderationMuteHideInput.value, "1");
assert.equal(controller.moderationSpamHideInput.value, "3");
assert.equal(
controller.moderationStatusText.textContent,
"Moderation defaults restored.",
);
assert.equal(controller.moderationSaveButton.disabled, true);
controller.moderationBlurInput.value = "7.8";
controller.moderationBlurInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
controller.moderationSpamHideInput.value = "8";
controller.moderationSpamHideInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
const saveResult = await controller.handleModerationSettingsSave();
assert.equal(saveResult.success, true);
assert.deepEqual(storedSettings, {
blurThreshold: 7,
autoplayBlockThreshold: 2,
trustedMuteHideThreshold: 1,
trustedSpamHideThreshold: 8,
});
controller.moderationBlurInput.value = "";
controller.moderationAutoplayInput.value = "";
controller.moderationMuteHideInput.value = "";
controller.moderationSpamHideInput.value = "";
controller.moderationBlurInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
controller.moderationAutoplayInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
controller.moderationMuteHideInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
controller.moderationSpamHideInput.dispatchEvent(
new windowRef.Event("input", { bubbles: true }),
);
assert.equal(controller.moderationSaveButton.disabled, false);
const revertContext = await controller.handleModerationSettingsSave();
assert.equal(revertContext.success, true);
assert.deepEqual(storedSettings, {
blurThreshold: 3,
autoplayBlockThreshold: 2,
trustedMuteHideThreshold: 1,
trustedSpamHideThreshold: 3,
});
});